在多线程环境中与Hibernate会话交互的合适方式

在多线程环境中与Hibernate会话交互的合适方式,hibernate,hibernate-5.x,Hibernate,Hibernate 5.x,当需要使用Hibernate使用会话时,获取会话getcurrentsession()或opensession()的最佳方法是什么 正如这里提到的,getcurrentsession不能用于web应用程序 虽然会话不安全,但由于这个原因,它不适合使用getcurrentsession吗?是否需要手动使用opensesion和commit&close flush 我需要一个明确的澄清。谢谢大家 PS:我使用hibernate和Spring Boot应用程序进行测试。如果您的类路径中有Spring

当需要使用Hibernate使用会话时,获取会话getcurrentsession()或opensession()的最佳方法是什么

正如这里提到的,getcurrentsession不能用于web应用程序

虽然会话不安全,但由于这个原因,它不适合使用getcurrentsession吗?是否需要手动使用opensesion和commit&close flush

我需要一个明确的澄清。谢谢大家


PS:我使用hibernate和Spring Boot应用程序进行测试。

如果您的类路径中有
Spring Boot AutoFigure
,很可能它已经在为您配置
EntityManager工厂了。如果您的类路径上没有这个,那么将
SessionFactory
的bean配置转换为
EntityManagerFactory
非常容易。完成之后,您可以通过在Springbean中执行以下操作超级简单地获得一个实例

@Service
public class MyBookServiceImpl implements BookService {
  @PersistenceContext
  private EntityManager entityManager;

  @Transactional
  public void doSomeFancyHibernateThing() {
    List<Book> allBooks = entityManager.createQuery( "FROM Book", Book.class )
       .getResultList();
  }
}
如果要使用
#openSession()
,则返回的
会话
对象的生命周期和生存期取决于您,以确保您能够适当地关闭其资源。换言之,上述简单方法变为:

public void doSomeFancyHibernateThing() {
  Session session = sessionFactory.openSession();
  try {
     // do something here
  }
  catch ( Exception e ) {
     // do whatever
  }
  finally {
    if ( session != null && session.isOpen() ) {
      session.close();
    }
  }
}
如您所见,答案顶部的JPA等价物与使用
getCurrentSession()
的hibernate配置非常相似

这里最大的好处是使用JPA(顶部的示例)可以直接删除Hibernate上的所有依赖项。如果您发现遇到一个用例,需要JPA不公开的特定于Hibernate的特性,您仍然可以通过如下方式展开EntityManager来轻松获得会话:

Session session = entityManager.unwrap( Session.class );
// do whatever you need with a session easily.

您应该使用@Transaction而不是手动创建会话。为什么要尝试进入休眠状态?使用Spring数据或JPA。这只是为了学习,集成hibernate而不是Spring数据。所以我会移除弹簧启动标签。谢谢你的解释。作为您的回答,在web应用程序中使用`#getcurrentsession()`是一个好主意吗?我已经看到,上面提到的hibernate教程显然没有使用“getcurrentsession()”这类Web应用程序上下文。顺便说一句,从您的回答中,我觉得在web应用程序中使用`#getcurrentsession()`并不是问题。对吗?我的回答涵盖了这一点。您可以使用它,但前提是您设置了特定的配置属性。如果不这样做,就会产生问题。让Spring为您提供您所需要的是一种普遍接受的做法,因为使用Spring的一个主要原因是让它为您处理许多平凡的样板文件,这样您就可以专注于应用程序的需要。谢谢,伙计。我认为那些教程是不正确的。你可以在这里签入它说不要使用getcurrentsession甚至hibernate.current\u session\u context\u class=线程配置。谢谢你的帮助不,没有。它指出,
会话
不是线程安全的,因此您不应该跨线程边界共享它。不,它在哪里说您不能在多线程环境中使用
#getCurrentSession()
。它明确指出,如果您希望这样做,您应该将该配置属性设置为
thread
,以使其正常工作。谢谢@Naros,我现在可以清楚地理解了。通过这两种方法,可以在具有特定配置方式的多线程环境中实现每个请求的会话模式(仅适用于
getcurrentsession
)。
Session session = entityManager.unwrap( Session.class );
// do whatever you need with a session easily.