Hibernate延迟加载 或 no session or session was closed 问题的解决(OpenSessionInViewFilter使用)

本文介绍了解决Hibernate在配置many-to-one或one-to-many时出现的nosessionorsessionwasclosed问题的方法。通过设置lazy属性为true并启用OpenSessionInViewFilter过滤器,在不牺牲性能的情况下实现了延迟加载。

Hibernate延迟加载 或 no session or session was closed 问题的解决(OpenSessionInViewFilter使用)

 

在Hibernate配置文件中配置many-to-one 或者 one-to-many 等情况时.设置lazy="true"时 在查询对结果操作时会出现以上情况.将lazy="true" 改为 lazy="false" 可以解决问题.但那就脱离了延迟加载.
实现延迟加载的解决办法由很多.我采用了比较简单的方法:
      使用:OpenSessionInViewFilter
           在web.xml 添加如下代码即可:

<filter>
      <filter-name>hibernateFilter</filter-name>
        <filter-class>
           org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
         </filter-class>
      </filter>
<filter-mapping>
   <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>

    
(以上代码struts2.0据说需要在web.xml中作为第一个filter,即所有filter的上面。位置不对可能不起作用)
    如果你是通过struts配置文件中以 ContextLoaderPlugIn插件 认识spring配置文件的话,那么 OpenSessionInViewFilter 加载的spring配置文件极可能与插件加载的不是同一个对象.因为他们的key值不一样.解决办法是删除、注释掉struts配置文件中的ContextLoaderPlugIn。在web.xml中认识:

     web.xml 中添加:
  

   <listener>
     <listener-class>
        org.springframework.web.context.ContextLoaderListener
     </listener-class>
   </listener>

  
以上代码可解决:No WebApplicationContext found: no ContextLoaderListener registered异常


  
它回去查找默认文件名为applicationContext.xml的文件,如果你的名字不一样 需要显示配置该文件。以上工作完成后即可实现,Hibernate延迟加载。

<think>嗯,我现在遇到了Hibernate中的LazyInitializationException异常,提示“no session or session was closed”。这个问题让我有点困惑,我得仔细想想怎么解决它。首先,我需要理解这个异常为什么会发生。 根据引用里的内容,Hibernate在查询操作完成后会自动关闭session,而延迟加载(Lazy Loading)的特性会导致在session关闭后尝试访问未加载的关联对象时抛出这个异常。比如,我有一个实体类ProductType,它有一个childtypes的集合属性,这个属性被设置为延迟加载。当Hibernate从数据库获取ProductType对象后,session被关闭了,之后如果代码试图访问childtypes,就会触发这个异常,因为session已经不可用了。 那么,解决这个问题的思路是什么呢?引用里提到了几种方法。首先,关闭延迟加载特性。不过这样做可能会影响性能,因为会立即加载所有关联数据,特别是当关联数据量大时,会增加数据库的负担。所以这个方法可能不是最优的。 另一种方法是延长session的生命周期,确保在需要访问关联对象时session仍然打开。比如使用Open Session in View模式,这在Web应用中比较常见。通过在请求开始时打开session,在视图渲染结束后关闭,这样在渲染过程中访问延迟加载的属性就不会出问题了。引用里的OpenSessionInViewFilter就是一个例子,不过代码示例中的过滤器似乎是在处理完请求之后关闭session,可能需要调整过滤器的执行顺序,确保在视图渲染前session是打开的,之后才关闭。 另外,还可以在查询时使用Hibernate的Fetch Join来主动加载关联数据,比如HQL中使用JOIN FETCH者Criteria API中的setFetchMode。这样,在查询主实体时,关联的集合会被立即加载,避免了延迟加载问题。这种方法适用于明确知道需要哪些关联数据的场景。 还有一种方法是使用Hibernate.initialize()方法,在session关闭前手动初始化代理对象。比如在获取到ProductType对象后,调用Hibernate.initialize(productType.getChildtypes()),这样childtypes集合会被立即加载,之后即使session关闭,数据也已经存在了。 此外,调整事务边界也是一种解决方式。确保在业务逻辑层中完成所有需要访问延迟加载属性的操作,而不是在表示层(如JSP页面)中处理。这样,在事务尚未提交、session仍处于打开状态时,就能访问到关联数据。 现在需要综合这些方法,选择适合当前应用场景的解决方案。比如在Web应用中,使用Open Session in View模式比较方便,但需要注意潜在的性能问题。如果应用结构分层清晰,可能更适合在服务层中通过Fetch JoinHibernate.initialize()来预先加载所需数据,避免在视图层处理数据加载。 另外,检查Hibernate的配置是否正确,比如是否启用了延迟加载,以及是否有其他配置影响了session的生命周期。例如,使用Spring框架的话,可以通过配置OpenSessionInViewFilterOpenSessionInViewInterceptor来管理session的生命周期。 总结一下,可能的解决方案有: 1. 使用Fetch Join主动加载关联数据。 2. 在session关闭前手动初始化代理对象。 3. 配置Open Session in View模式延长session生命周期。 4. 调整事务边界,确保在session打开时访问延迟加载属性。 5. 关闭延迟加载(不推荐,影响性能)。 需要根据具体情况选择合适的方法。比如,如果问题出现在JSP页面渲染时,可能适合用Open Session in View;如果在业务逻辑中已知需要访问某些关联数据,使用Fetch Join更高效。</think>### 如何解决 Hibernate LazyInitializationException 异常(no session or session was closed)? #### 问题原因 该异常是由于Hibernate的**延迟加载(Lazy Loading)**特性与**Session生命周期不匹配**导致的。当通过`get()``load()`方法获取实体后,如果Session已关闭,再尝试访问未加载的延迟关联对象(如集合属性),就会触发`LazyInitializationException`[^3][^5]。 --- #### 解决方案(逐步分析) ##### 1. **使用`JOIN FETCH`主动加载关联数据** 在查询时通过HQLCriteria API**立即加载所需关联数据**,避免延迟加载。 ```java // HQL示例:使用JOIN FETCH加载childtypes String hql = "SELECT pt FROM ProductType pt JOIN FETCH pt.childtypes WHERE pt.id = :id"; Query query = session.createQuery(hql).setParameter("id", 1); ProductType productType = (ProductType) query.uniqueResult(); ``` - **优点**:精确控制加载范围,减少数据库冗余查询。 - **缺点**:需提前明确需要加载的关联字段。 ##### 2. **手动初始化代理对象** 在Session关闭前,通过`Hibernate.initialize()`强制加载延迟集合: ```java ProductType productType = session.get(ProductType.class, 1); Hibernate.initialize(productType.getChildtypes()); // 手动初始化集合 session.close(); // 后续代码可安全访问childtypes ``` - **适用场景**:明确知道需要访问哪些关联对象。 ##### 3. **配置Open Session in View模式** 在Web应用中,通过过滤器拦截器**延长Session生命周期至视图渲染完成**,确保页面渲染时Session仍处于打开状态。 **Spring配置示例**: ```xml <!-- web.xml中配置OpenSessionInViewFilter --> <filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值