【问题标题】:hibernate jpa: Session is closed!hibernate jpa:会话已关闭!
【发布时间】:2011-02-28 18:02:49
【问题描述】:

应用基于 Spring 2.5.5 和 hibernate 3.2.0 GA。

我的 DAO 中有以下方法可以获取附加到指定用户的 MessageEntities:

public MessageEntity findByUserId(int userId) {
      List<MessageEntity> result = (List<MessageEntity>) em.createNamedQuery(MessageEntity.Q_BY_USER_ID).setParameter("userId", userId).getResultList();
      if (!result.isEmpty()) {
         return result.get(0);
      } else {
         return null;
     }
}

我需要从我的集成测试中调用这个方法来检查系统的行为是否有效。只要这个方法不是事务性的,我得到的只是 org.hibernate.SessionException: Session is closed!。避免这种情况的最简单方法是使用 @Transactional(readOnly = true) 标记 findByUserId 方法。但据我了解,事务管理应该是服务层的职责,以避免不必要的事务创建。所以,我的问题是:我怎样才能正确地摆脱 SessionException

【问题讨论】:

    标签: java hibernate spring jpa transactions


    【解决方案1】:

    需要在事务范围内执行所有数据库操作。正如您所确定的,它通常被认为是让您的数据库模型的服务层处理事务的良好设计。唯一的限制是您必须调用服务模型才能进入事务范围,这在测试期间可能是不可取的。

    我建议使用spring 提供的测试 fascilites。见9.3.2.3 Transaction management

    你也可以在测试你的方法之前手动创建一个事务,例如,通过

    Session sess = factory.openSession();
    Transaction tx = null;
    // try catch 
    tx = sess.beginTransaction();
    findByUserId(userId);
    tx.commit();
    tx.rollBack();
    

    【讨论】:

      【解决方案2】:

      将以下注释放在测试类的顶部。

      @RunWith(SpringJUnit4ClassRunner.class)
      @Transactional
      @ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
      

      我也不担心在 DAO 中添加额外的 @Transactional。 Spring 通常会在创建另一个事务之前检查您是否已经在一个事务中(在同一个线程中)。

      “但据我了解,交易 管理应该是职责 服务层以避免不必要的 交易创建。”

      This is more of a design choice(例如 Spring Roo 就违反了这个)

      【讨论】:

        【解决方案3】:

        你可以在你的控制器方法上使用这个注解:

        @Transactional(readOnly = true)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-26
          • 2011-10-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-06
          • 2010-11-29
          相关资源
          最近更新 更多