Hibernate延迟加载和会话关闭的矛盾解决方案

当持久层利用session的load()的方法去查询数据时,返回的只是虚拟代理,此时并没有真正的发送sql语句,如果在视图上使用到查询的数据时,此时sql语句才会真正发出,但这时候会话已经被关闭,无法在获取到数据。又或者在一对多的关联场景下,存在懒加载情况,也会出现延迟加载和会话关闭的矛盾。

一、利用Spring的OpenSessionInViewFilter过滤器延长会话的生命周期

web.xml中配置过滤器


    osiv
    org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
  
  
    osiv
    *.do
  

配置完过滤器后,session的生命周期就会延长直到视图渲染完成后才结束session。

存在的问题:
  在高并发的情况下、影响性能。因为这样一来,每个从这个过滤器过的请求的session都要被延长生命周期,因为会话上绑定了数据库连接。所以很有可能使数据库连接被某些无用的session占用,导致真正需要连接的会话被阻塞。

二、利用Hibernate工具类的isInitialized方法来解决

以user为例,在控制代码中,提前初始化视图上需要用到的数据:

    /*
     * 利用Hibernate工具类的isInitialized方法,判断user是否被初始化
     * 是的时候返回true,否则返回false
     * 如果没有被初始化则用Hibernate工具类的initialize将对象初始化
     */  
if(!Hibernate.isInitialized(user)) {
        Hibernate.initialize(user);
    }

但是这样的做法就需要我们去对代码的逻辑做一些修改,并且使方法和hibernate有了一定的耦合。

三、自定义过滤器

和Spring的OpenSessionInViewFilter一样,我们可以自己定义一个过滤器,来延长会话的生命周期。
拿到SpringIoC容器:

ServletContext sc = requset.getServletContext();
WebApplicationContext ctx = 
            WebApplicationContextUtils.getWebApplicationContext(sc);

从容器中取出Session并在chain.doFilter(request, response);前后分别开启和关闭会话。这种做法和Spring的OpenSessionInViewFilter没什么本质区别。

你可能感兴趣的:(Hibernate延迟加载和会话关闭的矛盾解决方案)