出现原因:
Hibernate允许对关联对象及属性延迟加载,前提是这个操作在同一个Hibernate
session范围内进行.如果发生这样的情况,当service层返回了一个启用延迟加载功能的domain对象给web层,而web层访问到这些需要延迟加载的对象或属性时,由于加载domain对象的session已经关闭导致无法访问,就会出现访问异常.
解决方法:
我们可以使用一个过滤器,在web请求时给它绑定一个Hibernatesession,这样就可以保证整个请求的过程中session都是开启的,可以进行延迟加载的操作.
Spring就提供了这个过滤器----OpenSessionInViewFilter,它把Hibernate
session绑定到请求线程中,session将自动被Spring的事务管理器管理.即使Service层的事务完成,session也会开启以支持延迟加载操作.
具体做法就是在web.xml中配置这个过滤器:
<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>
该解决方法的优缺点:
举个现实工程中的例子:
如果User和Department是多对一的实体关联关系,我们要在页面中显示user的信息,user中的Department使用懒加载.
使用OpenSessionInViewFilter,service层提供一个queryUser()方法就可以搞定,懒加载会自动在web层发起调用时触发.使用filter的感觉倍儿爽,轻轻松松实现了想用就查不用不查的效果,若项目不大的话,service层代码又好开发好维护.
让我们来想一想会不会有性能问题.如果项目偏大又有高并发,这么做就显得不那么爽了.为什么呢?每一个web请求都会绑定一个Hibernate
session,所有的请求都绑定session后,就意味着所有的请求都会占用一个数据连接,直到请求处理完成后!也就是说web请求对数据连接的占用会比原来长很多,甚至有的web请求根本不需要使用数据连接,这种对数据连接资源访问的并发性更会出现性能瓶颈.因为我们的瓶颈多是出现在数据库上啊~
有什么好的解决方案吗?
有啊,让需要连接数据库的请求绑定session,不需要的不绑定就得了嘛,是,只是在过滤器前面加过滤器的技术我还不太会.
说个能实现的吧,就是不用OpenSessionInViewFilter了.那懒加载异常怎么解决啊?我们换个思路,把懒加载的事在service内完成,不让它跨出service到web层了.这就要在service层设计好多元的接口,还从上面的例子说,我在service层写两个接口,一个叫getUserWithDepartment(),一个叫getUserWithoutDepartment().
ITOO项目经验总结:
ITOO中并没有使用Hibernate的懒加载,当时不必要的关联查询导致系统显示缓慢是靠优化sql语句解决的.为什么我们没用懒加载这么好的东东?因为我们的延迟加载操作完全超出了Hibernate
session的范围,一个是EJB容器中的session,一个是Spring中的Hibernate
session,超出范围当然就用不了啦.
版权声明:本文为博主原创文章,未经博主允许不得转载。