异常描述:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
懒加载(延迟加载):
懒加载为hibernate中比较常用的特性之一。它通过生成一个代理类的形式,在你真正需要使用该对象里面的一些属性的时候才会去数据库访问并得到数据,也就是发出对应的sql。这样能减少不必要的sql查询,提高性能。
- 常见使用懒加载的地方:
session.load()方法:
- 方法加载出来的对象是class的代理对象
- 在加载其属性的时候发出sql语句(按照需求加载,延迟加载)
- 获取标识符属性是不用延迟加载的,获取普通属性是需要发出sql语句的
- 标识符属性对于延迟加载不起作用
*.hbm.xml映射文件中的关系映射:
- 一对一的懒加载(不常用。一对一主表中的每一条数据只对应从表的一条数据库,不会产生多余的sql。且主表有contrained=true,所以主表是不能懒加载的。从表可以有懒加载)
- 一对多和多对多的懒加载(主要用。主表的一条属性会对应多条从表属性,运用懒加载,在需要用到从表的属性时才发送sql请求)
- 多对一的懒加载(多对一与一对一情况相同,但hibernate默认lazy)
异常的产生:
如图所示:
在Action中我们调用service来开启事务,开启session,而当请求出了Action之后,事务和session会提交和关闭。Action里用到了懒加载,在request离开Action前,懒加载只会用session查询需要的内容。当request离开Action,close session。这时候如果我们在Result(页面)中需要用到懒加载的属性,因为没有session进行查询,所以会出现懒加载异常。
解决方法:
如图所示:
在request离开Action后不要关闭session,而让session在执行完流程后在过滤器(OpenSessionInViewFilter过滤器)中关闭
- 代码解决实现:
- 在web.xml中添加代码(注意:该过滤器要添加在Struts核心过滤器StrutsPrepareAndExecuteFilter之前)
<!-- 配置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>
顺便说一下,这里过滤的url-pattern为*.action,这也是为什么我们要配置action扩展名的原因,只过滤action