如何正确释放Hibernate Session使用的资源


最近一个项目使用的SpringMVC+SpringSecurity+Hibernate的开发框架,由于需要使用到多个视图表现方式,所以在Web.xml中针对不同的视图表现方式配置了不同的初始化入口,这直接导致一个项目中存在多个连接缓冲池,其中SpringSecurity单独使用一个连接缓冲池,业务代码单独使用一个,这就引出来下面的问题。

在业务代码中,由于在Service层进行了事务控制,所以业务代码的DAO继承HibernateDaoSupport之后,直接使用getSession().createSQLQuery的方式操作数据库,不用自己管理session。

而在SpirngSecurity中,由于自己实现了UserDetailsService接口,在自定义的UserDetailsService中查询了数据库,获得用户信息。在做压力测试的时候发现很容易就出现can’t open connection的问题,并且在停止压力测试之后,已经打开的链接并不不会被关闭。通过检查代码发现,在UserDetailsService中并没有进行事务控制,也没有对Session进行释放资源的操作,问题就出在这里了。

由于业务代码使用了事务控制,在事务结束的时候框架会释放Session关联的资源,而UserDetailsService中没有事务控制,所以我们需要手动进行Session相关资源的释放。将getSession().createSQLQuery修改为Session sess = getSession(); sess.createSQLQuery,查询完数据之后执行super.releaseSession(sess);释放Session资源。这样子操作之后,没有再出现无法打开连接的问题,并且在Connection空闲指定时间之后,自动关闭了。

进一步阅读super.releaseSession()方法的代码发现,在HibernateDaoSupport中是通过SeesionFacotryUtils.releaseSession(Session, SessionFactory)进行Session资源释放的,在这个方法中,对Session进行了是否存在事务的判断,如果Session本身仍然在事务内,则不关闭。想必,如果业务层存在事务控制,同时在DAO进行releaseSession的操作时,Session并不会真正的被关闭,而要等到事务结束的时候由事务进行关闭操作了。

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s