【问题标题】:How can I mix Hibernate and Swing in a good manner如何以良好的方式混合 Hibernate 和 Swing
【发布时间】:2011-03-05 04:25:41
【问题描述】:

我有一些关于与 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;
     }
    

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

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

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

【问题讨论】:

  • 因为我的问题是如何以良好的方式混合休眠和摇摆。
  • 哈哈哈...哈哈。这是一个很好的问题:D @blow

标签: java hibernate swing service-layer


【解决方案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 查询,我建议您将 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
   }

}

也许你想看this线程

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

【讨论】:

  • 嗨!谢谢你,你的回答给了我antoher question..为什么有一个服务层很好?我更新了我的帖子。
  • 好的,我想现在明白了.. 我希望 :) 再次感谢!
  • @blow 请参阅stackoverflow.com/questions/2597219/… 了解我在哪里使用服务(用例驱动和事务边界)和存储库(检索实体)请记住,您不需要每个存储库您拥有的实体。 如果需要,您只需编写一个存储库
猜你喜欢
  • 2011-08-29
  • 2013-01-18
  • 2011-05-10
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多