【问题标题】:Hibernate session handling when using lazy loading in a JSF web application在 JSF Web 应用程序中使用延迟加载时的休眠会话处理
【发布时间】: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


    【解决方案1】:

    嗯,简单的答案是“这取决于...”。

    如果您的 web 应用程序具有高流量,并且有大量用户,我会为每个请求使用一个休眠会话。

    如果您的用户很少有长而复杂的会话,我会将一个休眠会话映射到每个 http 会话。

    使用第二种解决方案,您显然忘记了 LazyLoading 异常,但您还保持数据库会话处于打开状态,并且通常不是很活跃。

    使用第一个,理论上您更愿意吸收高流量,但您必须使用 session.refresh 将对象“重新连接”到数据库,然后才能使用它们。

    在某些应用程序中,我只是两者都做。绝大多数用户都有一个请求范围的数据库会话,他们使用的屏幕是相应编码的。我为高级用户使用会话范围的数据库会话,通常使用特定的屏幕。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-28
      • 2017-12-19
      • 2011-06-15
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多