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



多线程环境的上下文,如Web应用程序,每当需要使用Hibernate使用会话时,获取会话getcurrentsession((或opensession((的最佳方法是什么?

正如这里的opensession与getcurrentsession一样,它提到getcurrentsession不能在Web应用程序中使用。

虽然会话不是踏踏安全的,但由于这个原因,它不适合使用 getcurrentsession ?是否需要使用opensesion并手动提交和关闭刷新?

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

PS :我将休眠与 Spring 启动应用程序一起使用用于测试目的。

如果您的类路径中有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(),请务必提供以下配置的休眠,以便它将当前会话查找与线程局部变量绑定,确保每个线程提供自己的会话对象:

hibernate.current_session_context_class=线程

使用上述方法的好处是您无需担心Session的生命周期管理,它将在您的交易结束时自动关闭和释放。

例如:

@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()非常相似。

这里的强大好处是使用 JPA(顶部的示例(直接删除 Hibernate 上的任何和所有依赖项。 如果您发现遇到需要 JPA 未公开的休眠特定功能的用例,您仍然可以通过解开 EntityManager 来轻松获取会话,如下所示:

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

最新更新