当前位置: 首页 > 知识库问答 >
问题:

在JSF web应用程序中使用惰性加载时的Hibernate会话处理

都乐逸
2023-03-14

Javaworld Hibernate入门教程状态:

会话的实例是轻量级的,并且创建和销毁的成本很低。这很重要,因为您的应用程序需要一直创建和销毁会话,也许是在每次请求时。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();
    }
}

当涉及到懒惰加载时,您肯定会得到一个Lazy初始化异常,当几分钟或几小时后,一些用户交互需要访问存储在用户会话中的对象上的懒惰加载集合,并使用上述代码从Hibernate读取,因为会话用来装载它很久以前就关闭了。(我不认为避免懒惰加载是这里最常提出的解决方案。)

继续阅读这里,我还发现:

您可以由所有DAO使用同一个会话,在初始化期间打开,在关闭时关闭。请注意,Hibernate参考提到“每个操作的会话”是一种反模式:

"不要使用每个操作的会话反模式:不要为单个线程中的每个简单数据库调用打开和关闭会话。"

在我看来,这与上面提到的方向有些矛盾。我必须保持会话打开并重新使用它,或者我不这样做?我假设,对于任何操作,只要在会话上打开会话而从不关闭它们,就意味着实现了内存泄漏。在这里,使用应用程序范围的会话池也可能不够,因为一个线程可以签出一个会话,而另一个线程可能访问绑定到该会话的延迟加载集合,这就是并发性问题。

Spring框架中有一些解决方案,但如果没有这些解决方案,并且给定了一个长期运行、基于JSF、多线程和多用户的web应用程序:如何更好地管理它?

共有1个答案

阎佑运
2023-03-14

简单的回答是“这取决于……”。

如果你的webapp流量大,用户数量多,我会对每个请求使用一个hibernate会话。

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

对于第二种解决方案,您显然忘记了LazyLoading异常,但是您也保持db会话打开,并且通常不是非常活跃。

有了第一个,理论上你更准备吸收高数据量,但是在使用它们之前,你必须使用session.refresh将你的对象“重新连接”到数据库。

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

 类似资料:
  • 我们目前有几个@OneToOne关系,由于已知的惰性加载的限制,它们总是会急切地从反方向获取。 为了启用逆关系的延迟加载,我正在尝试启用构建时字节码检测。 到目前为止我所做的... 这些关系现在不再急切地加载...但是它们也不会延迟加载,它们只是静默地返回null。 我尝试从实体中删除接口和字段,因为我不确定是否需要这样做,在此之后,我在启动时不再获得消息,并且默认情况下返回到急切加载。 我是不是

  • 问题内容: 您如何在Java Desktop Swing应用程序中进行Hibernate会话管理?您是否使用一个会话?多个会议? 以下是有关此主题的一些参考资料: http://www.hibernate.org/333.html http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-ap

  • 问题内容: hibernate中的property标签的lazy属性允许按照以下链接延迟加载属性:http : //docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping- declaration -属性 lazy(可选-默认为false):指定在首次访问实例变量时应延迟获取此属性。它需要构建时字节码检测

  • 这组订单应该是惰性加载的,但我得到以下异常:org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是org.hibernate.lazyInitializationException:未能懒洋洋地初始化Role:...,没有会话或会话被关闭 根本原因:org.hibernate.lazyInitializationExcept

  • 问题内容: 我目前正在开发我的一个(相当大的)宠物项目,这是一个Swing应用程序,它本质上需要多线程。几乎所有用户交互都可能通过Internet从某些远程服务器获取数据,因为我既不能控制这些服务器,也不能控制Internet本身,因此不可避免的是需要较长的响应时间。EDT忙时,Swing UI显然无法重绘自身,因此所有远程服务器调用都需要由后台线程执行。 我的问题: 后台线程获取的数据被本地(内

  • 我在GWT应用程序中使用hibernate,其中我有一个单独的客户机/服务/业务/dao层。 服务/业务层使用dao层获取/更新用于请求处理的模型。问题是,我遵循DOA类方法中打开/关闭hibernate会话的反模式。 一般的Hibernate指南似乎建议,我们应该有一个请求范围的会话。这可以在几个地方完成,比如servlet过滤器或服务层。我们可以打开会话并将其注入到DAO层,并在完成请求之前在