懒加载异常的解决办法

采用的是SSH2框架,要实现一个级联功能,具体实现如下:

Department部门包括许多下级Department,在查询第一级Department时,一切OK,但是当查询第一级Department下的子Department时,出现了如下错误,其中Department.hbm.xml中的配置文件为

    <many-to-one name="parent"class="Department" column="parentId"lazy="false"></many-to-one>  

这里表示Department实体中有parent这个属性,一个parent有多个Department,也就是多对一关系

以及Stacktraces

1、org.apache.jasper.JasperException:javax.el.ELException: Error reading ‘name’ on typecn.itcast.oa.domain.Department_$$_javassist_1

。。。。。省略。。。。。。

2、javax.el.ELException: Error reading ‘name’ ontype cn.itcast.oa.domain.Department_$$_

javassist_1

。。。。。省略。。。。。。

3、org.hibernate.LazyInitializationException:could not initialize proxy - no Session

。。。。。省略。。。。。。

在上面的三条错误消息中,第三条为关键错误提示LazyInitializationException(懒加载异常在默认情况下,hibernate为懒加载),这意味着在读取数据的时候,Session已经关闭。

解决办法:

1、 设置懒加载为false,在默认情况下,hibernate为懒加载,因此需要设置不为懒加载,在Department.hbm.xml中设置如下:

<many-to-one name="parent"class="Department" column="parentId"lazy="false"></many-to-one> 

把lazy的值设置为false,也就是说,当加载了父Department后,他的所有子Department都会被加载,这就会出现另外一个问题:当父Department下有很多子Department时,会加载所有的子Department,会造成性能很低。

那么我们能不能把他改为用的时候才加载,不用的时候则不加载?(默认还是懒加载,但是要你在用的时候能找到Session,能找到Session就能从数据库中读取数据)

2、采用拦截器
这里写图片描述
上面代表一次请求,需要经过Action和拦截器,左边方框为Action,中间方框为Result(页面),右边方框为Filter拦截器。

     Action表示我们要执行的结果,在Action里调用的是Service业务方法(Service方框),我们常用的做法是在Service中开和关事物,以及openSession和close Session,由于我们是在Result(页面)中才使用到懒加载的属性(此时Session已经关闭)。为了解决这个问题,必须要把close Session这一步推迟到Result后才能关闭。这里我们采用的是spring中OpenSessionInViewFilter(这是一个过滤器)来实现。

具体代码如下:

Department.hbm.xml中的配置保持不变,如下所示:

<many-to-one name="parent" class="Department"column="parentId"></many-to-one> 

在web.xml中添加一个过滤器,如下所示:

<!-- 配置Spring的OpenSessionInViewFilter过滤器,以解决Hibernate的懒加载异常(LazyInitializationException) -->  
    <filter>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>  
    </filter>  
    <filter-mapping>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
       <url-pattern>*.action</url-pattern>  
    </filter-mapping>  

这样就可以实现需要的时候才加载,不需要的时候不加载,同时默认页为懒加载

一般情况下,如果没有使用Filter或者将lazy设置为false的话,在Action方法中使用完Session就会关闭Session,因此如果在Action方法外使用Session中的数据就会报懒加载异常。

     OpenSessionInViewFilter的作用是将Session的关闭放到Filter中,因此,我们在Action方法外使用Session时,就不会出现Session已经关闭的异常了。

下面这张图跟上面这张图差不多,可以参考一下。
这里写图片描述
什么是懒加载?

有一个Student类,它有一个属性Teacher t对象,当你load一个Student s 时,这个时候t = null,当你调用s.getT时,它才去加载t对象,也就是说:当你需要使用t的时候,才去加载至于proxy:
<class name="com.test.Student"table="student" lazy="true">  
这种方式等价于  
<class name="com.test.Student"table="student" proxy="com.test.Student"> 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis懒加载是指在查询关联对象时,只有在真正使用到这些对象时才会进行加载,而不是在查询主对象时就一次性加载所有关联对象。这样可以减少不必要的数据库查询,提高查询效率。 在MyBatis中,可以通过配置来实现懒加载。一种常用的方式是使用MyBatis的association和collection标签来配置关联对象的懒加载。association用于一对一关系的懒加载,而collection用于一对多关系的懒加载。 例如,假设有一个User对象关联一个Order对象列表,可以通过如下配置来实现懒加载: ```xml <resultMap id="userResultMap" type="User"> <id property="id" column="id" /> <result property="name" column="name" /> <collection property="orders" ofType="Order" select="selectOrdersByUserId" fetchType="lazy" /> </resultMap> ``` 上述配置中,fetchType="lazy"表示orders列表的加载方式为懒加载。当查询User对象时,只有在访问orders列表时才会执行selectOrdersByUserId查询语句,实现懒加载。 需要注意的是,懒加载需要确保在Session关闭之前访问关联对象,否则会抛出异常。可以使用Session的selectList方法来解决该问题,如: ```java List<User> users = session.selectList("selectUsers"); for (User user : users) { List<Order> orders = user.getOrders(); // 访问关联对象,触发懒加载 // ... } ``` 通过配置和正确使用Session,可以实现MyBatis的懒加载功能,提高查询性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值