Multithreading 在JSF web应用程序中使用惰性加载时的Hibernate会话处理
各国:Multithreading 在JSF web应用程序中使用惰性加载时的Hibernate会话处理,multithreading,hibernate,jsf,session,lazy-loading,Multithreading,Hibernate,Jsf,Session,Lazy Loading,各国: 会话的实例是轻量级的,并且创建和销毁成本较低。这一点很重要,因为您的应用程序需要始终创建和销毁会话,可能是在每次请求时。Hibernate会话不是线程安全的,按照设计,一次只能由一个线程使用 因为Tomcat在多个线程中处理HTTP请求,所以在web应用程序中线程安全是非常必要的。因此,我读到: 会话应该是每个方法的局部变量。通过这样做,DAO将成为无状态的,因此本质上是线程安全的,不需要任何同步 让我们以这种方式在基于JSF的web应用程序中实现它: private static fi
会话
的实例是轻量级的,并且创建和销毁成本较低。这一点很重要,因为您的应用程序需要始终创建和销毁会话,可能是在每次请求时。Hibernate会话不是线程安全的,按照设计,一次只能由一个线程使用
因为Tomcat在多个线程中处理HTTP请求,所以在web应用程序中线程安全是非常必要的。因此,我读到:
会话应该是每个方法的局部变量。通过这样做,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读取的,因为用于加载该集合的会话很久以前就关闭了。(我不认为懒惰加载,这是最常见的,作为一个解决方案。)
继续阅读,我还发现:
您可以由所有DAO使用同一个会话,在初始化期间打开,在关闭时关闭。请注意,其中提到“每个操作的会话数”是一种反模式:
“不要使用每操作会话反模式:不要在单个线程中为每个简单的数据库调用打开和关闭会话。”
在我看来,这与上面提到的方向有些矛盾。我必须保持会话打开并重新使用它,或者我不这样做?我假设,对于任何操作,只要在会话上打开会话而从不关闭它们,就意味着实现了内存泄漏。在这里,使用应用程序范围的会话池也可能不够,因为一个线程可以签出一个会话,而另一个线程可能访问绑定到该会话的延迟加载集合,这就是并发性问题
,但如果没有它,并且给出了一个长期运行、基于JSF、多线程和多用户的web应用程序:如何更好地管理它?好吧,简单的答案是“这取决于…” 如果你的webapp流量大,用户数量多,我会对每个请求使用一个hibernate会话 如果很少有用户使用长而复杂的会话,我会将一个hibernate会话映射到每个http会话 对于第二种解决方案,您显然忘记了LazyLoading异常,但是您也保持db会话打开,并且通常不是非常活跃 对于第一个,从理论上讲,您更愿意吸收高流量,但您必须在使用对象之前使用session.refresh将对象“重新连接”到数据库 在一些应用程序中,我两者都做。绝大多数用户都有一个请求范围的db会话,他们使用的屏幕也相应地编码。我为超级用户使用会话范围的db会话,通常使用特定的屏幕