Web应用程序等多线程环境的上下文,每当需要使用Hibernate使用会话时,获取会话的最佳方式是getcurrentsession()还是opensession()?
就像在这里opensession vs getcurrentsession一样,它已经提到过getcurrentsession不能在Web应用程序中使用。
虽然会话不是安全的,但由于这个原因它不适合使用getcurrentsession吗?是否需要使用opensesion并提交&手动关闭冲洗?
我需要明确澄清。谢谢大家。
PS:我使用了Spring Boot App的hibernate进行测试。
答案 0 :(得分:2)
如果您的类路径中有spring-boot-autocofigure
,则可能已为您配置EntityManagerFactory
。如果您的类路径上没有这个,那么将SessionFactory
的bean配置转换为EntityManagerFactory
非常容易。完成之后,只需在spring bean中执行以下操作即可获得超级实例
@Service
public class MyBookServiceImpl implements BookService {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void doSomeFancyHibernateThing() {
List<Book> allBooks = entityManager.createQuery( "FROM Book", Book.class )
.getResultList();
}
}
此时,您可以向服务类添加任何方法,以便执行该bean实现和使用EntityManager
实例所需的任何任务。您不需要关心多个线程等,因为spring会自动为您提供EntityManager
的实例,该实例可以安全地在该线程中使用而无需考虑其他线程。
注意我在这里说那个帖子是安全的。不要试图在另一个线程中使用该实例,并期望不存在复杂性或问题。
如果您认为必须使用SessionFactory
,无论出于何种原因,您都可以使用这两种方法中的任何一种,具体取决于您 希望管理会话生命周期的程度。
如果你想使用#getCurrentSession()
,重要的是你还提供以下配置休眠,以便它将当前会话查找与线程局部变量绑定,确保每个线程都给出自己的会话对象: / p>
的hibernate.current_session_context_class =螺纹
使用上述内容的好处是您无需担心Session
的生命周期管理,它将自动关闭&amp;在您的交易结束时发布。
例如:
@Transactional
public void doSomeFancyHibernateThing() {
Session session = sessionFactory.getCurrentSession();
// do something here, when the method exits, the session is closed & destroyed.
}
如果要使用#openSession()
,则返回的Session
对象的生命周期和生命周期将在您身上,以保证您处理正确关闭其资源的问题。换句话说,上面这个简单的方法就变成了这个:
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.