在多线程环境中与 Hibernate 会话交互的合适方式
Suitable way to interact with Hibernate sessions in multi-thread environment
Web 应用程序等多线程环境的上下文,每当需要使用 Hibernate 使用会话时,getcurrentsession() 或 opensession() 获取会话的最佳方法是什么?
这里opensession vs getcurrentsession提到getcurrentsession不能用在网络应用程序中。
虽然 session 不是安全的,但由于这个原因,它不适合使用 getcurrentsession 吗?是否需要手动使用opensesion和commit & close flush?
我需要一个明确的说明。谢谢大家
PS : 我将休眠与 Spring 启动应用程序一起用于测试目的。
如果您的 class 路径中有 spring-boot-autocofigure
,它很可能已经为您配置了 EntityManagerFactory
。如果您的 class 路径上没有它,那么将 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();
}
}
此时您可以向服务添加任何方法 class 您需要执行该 bean 完成和使用 EntityManager
实例所需的任何任务。您不需要关心多个线程等,因为 spring 会自动为您提供一个 EntityManager
的实例,可以在该线程中安全使用而无需担心其他线程。
注意我在这里说在那个线程中可以安全使用。不要试图在另一个线程中使用该实例并期望不会出现并发症或问题。
如果您认为出于任何原因必须使用 SessionFactory
,您可以使用这两种方法中的任何一种,具体取决于 您 想要管理的生命周期session.
如果您想使用 #getCurrentSession()
,重要的是您还要为休眠提供以下配置,以便它将当前 session 查找与 thread-local 变量绑定,确保每个线程给出自己的 session object:
hibernate.current_session_context_class=thread
使用上面的好处是你不需要担心Session
的生命周期管理,它会在你的交易结束时自动关闭和释放。
例如:
@Transactional
public void doSomeFancyHibernateThing() {
Session session = sessionFactory.getCurrentSession();
// do something here, when the method exits, the session is closed & destroyed.
}
如果您想使用 #openSession()
,那么返回的 Session
object 的生命周期和生存期由您负责,以确保您正确地处理关闭其资源。也就是说,上面的简单方法变成了这样:
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()
的使用非常相似,当与那个休眠配置配对时。
这里的最大好处是使用 JPA(顶部的示例)直接删除了对 Hibernate 的所有依赖。如果你发现你 运行 进入一个你需要 Hibernate-specific JPA 没有公开的功能的用例,你仍然可以通过解包 EntityManager 轻松获得 Session ,如下所示:
Session session = entityManager.unwrap( Session.class );
// do whatever you need with a session easily.
Web 应用程序等多线程环境的上下文,每当需要使用 Hibernate 使用会话时,getcurrentsession() 或 opensession() 获取会话的最佳方法是什么?
这里opensession vs getcurrentsession提到getcurrentsession不能用在网络应用程序中。
虽然 session 不是安全的,但由于这个原因,它不适合使用 getcurrentsession 吗?是否需要手动使用opensesion和commit & close flush?
我需要一个明确的说明。谢谢大家
PS : 我将休眠与 Spring 启动应用程序一起用于测试目的。
如果您的 class 路径中有 spring-boot-autocofigure
,它很可能已经为您配置了 EntityManagerFactory
。如果您的 class 路径上没有它,那么将 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();
}
}
此时您可以向服务添加任何方法 class 您需要执行该 bean 完成和使用 EntityManager
实例所需的任何任务。您不需要关心多个线程等,因为 spring 会自动为您提供一个 EntityManager
的实例,可以在该线程中安全使用而无需担心其他线程。
注意我在这里说在那个线程中可以安全使用。不要试图在另一个线程中使用该实例并期望不会出现并发症或问题。
如果您认为出于任何原因必须使用 SessionFactory
,您可以使用这两种方法中的任何一种,具体取决于 您 想要管理的生命周期session.
如果您想使用 #getCurrentSession()
,重要的是您还要为休眠提供以下配置,以便它将当前 session 查找与 thread-local 变量绑定,确保每个线程给出自己的 session object:
hibernate.current_session_context_class=thread
使用上面的好处是你不需要担心Session
的生命周期管理,它会在你的交易结束时自动关闭和释放。
例如:
@Transactional
public void doSomeFancyHibernateThing() {
Session session = sessionFactory.getCurrentSession();
// do something here, when the method exits, the session is closed & destroyed.
}
如果您想使用 #openSession()
,那么返回的 Session
object 的生命周期和生存期由您负责,以确保您正确地处理关闭其资源。也就是说,上面的简单方法变成了这样:
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()
的使用非常相似,当与那个休眠配置配对时。
这里的最大好处是使用 JPA(顶部的示例)直接删除了对 Hibernate 的所有依赖。如果你发现你 运行 进入一个你需要 Hibernate-specific JPA 没有公开的功能的用例,你仍然可以通过解包 EntityManager 轻松获得 Session ,如下所示:
Session session = entityManager.unwrap( Session.class );
// do whatever you need with a session easily.