4

我对与 Hibernate 的交互有一些疑问:

  1. 我是使用 openSession 还是 getCurrentSession(没有 jta,而是使用线程)?
  2. 如何将会话操作与 Swing GUI 混合使用?在 JavaBean 类中有类似以下代码的东西好吗?

    public void actionPerformed(ActionEvent event) {
        // session code
    }
    
  3. 我可以向包含 HQL 查询的实体添加方法,还是这是一种不好的做法?例如:

     // This method is in an entity MyOtherEntity.java class
     public int getDuration(){
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        int sum = (Integer) session.createQuery("select sum(e.duration) as duration from MyEntity as e where e.myOtherEntity.id=:id group by e.name").
            .setLong("id", getId());
            .uniqueResult();
        return sum;
     }
    

我怎样才能以更好和优雅的方式做到这一点?

更新 一个广泛使用的做法是制作一个服务/dao类来实现我们实体类的CRUD操作。但为什么这样好?为什么我必须为每个实体编写一个类来管理它?真正的优势在哪里?

更新 2 服务类是 DAO 模式?这是什么意思? Arthur Ronald FD Garcia 的存储库示例是一个 DAO 模式,这就是所谓的“服务层”吗?

4

1 回答 1

1

如果你想依赖普通的 Hibernate API,你可以使用服务层,因为

  • 它是用例驱动的
  • 划定事务边界

因此,您可以创建一个 AccountService,例如,

public static path.to.HibernateUtil.getSessionFactory;

public class AccountService {

    public void withdraw(Integer accountNumber, BigDecimal amount) throws Exception {
        /**
          * Here you set up Transaction boundaries
          */
        getSessionFactory().getCurrentSession().beginTransaction();

        // Some actions goes here

        getSessionFactory().getCurrentSession().getTransaction().commit();
    }

}

在服务层内执行某些操作时,您通常需要一个存储库。您可以将存储库视为数据提供者和存储在这里你可以看到我是如何实现我的存储库的。

如果您想要一个可维护和可读的 HQL 查询,我建议您将 HQL 查询外部化在一个多行和外部化 xml 文件中

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <query name="GIFT_CARDS_WITH_BUYER">
        <![CDATA[
            from 
                GiftCard c
            left join fetch 
                c.buyer
            where
                c.recipientNotificationRequested = 1
       ]]>
    </query>
    <query name="GIFT_CARDS_WITHOUT_NO_RELATIONSHIP">
        <![CDATA[
            from 
                GiftCard
        ]]>
    </query>
</hibernate-mapping>

所以在你的 Swing GUI 事件中,你可以调用你的服务层

public void actionPerformed(ActionEvent event) {
    // Some related Swing GUI actions goes here (retrieve User input, validate data and so on...)

    accountService.withdraw(accountNumber, new BigDecimal(amount));
}

在您的实体中使用持久性操作并不是一个好主意。如果您需要在实体中执行与持久性相关的问题,我认为最好将存储库作为参数传递给您的实体

public class Account {

   public void doSomething(AccountRepository repository) {
       // code goes here
   }

}

也许你想看到这个线程

我建议您看一下 Java Persistence with Hibernate 一书,第 9 章(使用对象)。ATT:仔细阅读

更新

为什么好有一个服务层?

首先

  • 它是用例驱动的(它描绘了您的应用程序应该做什么)

其次

  • 它划定事务边界

假设这里是你的服务层

public class MyService {

    public void doSomething() {
        getSessionFactory().beginTransaction();

        // A POJO doing some operation

        // Other POJO doing other operation

        // Another POJO doing another operation

        getSessionFactory().getTransaction().commit();
    }

}

请注意,您只需定义一个事务边界,而不是在每个 POJO 中定义每个事务边界。而且,如果您的 Swing GUI 中的业务规则需要在其他组件中使用,会发生什么情况。你会使用 Ctrl-c + Ctrl-v 吗?

于 2010-06-17T23:11:33.270 回答