【发布时间】:2014-07-11 05:16:00
【问题描述】:
Javaworld Get started with Hibernate tutorial 声明:
Session的实例是轻量级的,创建和销毁的成本很低。这很重要,因为您的应用程序将需要一直创建和销毁会话,可能在每个请求上。 Hibernate 会话不是线程安全的,按照设计,一次只能由一个线程使用。
因为Tomcat在多个线程中处理HTTP请求,所以线程安全在Web应用程序中是非常必要的。因此,我阅读了this answer:
会话应该是每个方法的局部变量。通过这样做,你的 DAO 将变得无状态,因此本质上是线程安全的,不需要同步
让我们在基于 JSF 的 Web 应用程序的深处以这种方式实现它:
private static final SessionFactory sessionFactory;
public Object read(Class c, Integer id){
try{
Session session = sessionFactory.openSession();
return session.get(c, id);
}finally{
session.close();
}
}
当涉及到延迟加载时,您肯定会在几分钟或几小时后获得 LazyInitializationException,当某些用户交互需要访问存储在用户会话中并从 Hibernate 中读取的对象上的延迟加载集合时代码,因为用于加载它的会话很久以前就关闭了。 (我不考虑将最常提出的延迟加载作为解决方案。)
继续阅读here,我也发现:
您可以改为由所有 DAO 使用同一个会话,在初始化期间的某个时间打开并在关闭时关闭。请注意,Hibernate Reference 提到“每个操作的会话”作为反模式:
“不要使用 session-per-operation 反模式:不要在单个线程中为每个简单的数据库调用打开和关闭 Session。”
在我看来,这在某种程度上与上面提到的方向相矛盾。我必须保持会话打开并重复使用它,不是吗?我假设只为任何操作打开会话而不关闭它们只是意味着实现内存泄漏。在这里使用应用程序范围的会话池可能还不够,因为一个线程可以签出一个会话,而另一个线程可能会访问一个绑定到该会话的延迟加载集合,这就是并发问题。
There are solutions in the Spring framework,但没有它,并且给定一个长时间运行的、基于 JSF 的多线程和多用户 Web 应用程序:如何更好地管理这个?
【问题讨论】:
标签: multithreading hibernate jsf session lazy-loading