如何以良好的方式混合Hibernate和Swing

时间:2010-06-17 21:06:12

标签: java hibernate swing service-layer

我对与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;
     }
    
  4. 我怎样才能以更优雅的方式做到这一点?

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

    更新2 服务类是DAO模式?这是什么意思? Arthur Ronald F D Garcia's repository example是DAO模式,这就是所谓的“服务层”吗?

1 个答案:

答案 0 :(得分: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();
    }

}

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

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

<?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
   }

}

也许你想看{4}}线程

我建议你看看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 ???