HibernateDaoSupport 类session未关闭导致的连接泄露问题 收藏
Spring+Hibernate做项目, 发现有member在不加事务的情况下就去调用 getSession() 方法, 结果导致数据库连接不能释放, 也无法正常的提交事务(只能做查询, 不能做save(), update()). 如果配合连接池使用的话, 不出几分钟就会导致连接池无法拿到新连接的情况.
不过, 只要给DAO或者Service加入了事务, 就不会出现连接泄漏的问题.
谈谈解决方案:
最佳方案: 加入事务, 例如 tx 标签或者 @Transactional 都可以.
最笨方案: 修改代码, 使用 HibernateTemplate 来完成相关操作:
public List queryAll( final String hql, final Object… args) {
List list = getHibernateTemplate().executeFind( new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query query = session.createQuery(hql);
for ( int i =0; i < args. length ; i++) {
query.setParameter(i, args[i]);
}
List list = query.list();
return list;
}
});
return list;
}
public Serializable save(Object entity) {
return getHibernateTemplate().save(entity);
}
但是缺陷显而易见, 要有N多的代码要进行改动.
HibernateDaoSupport 代码里面的原始说明文档指出直接调用getSession()方法必须用配套的releaseSession(Session session)来释放连接, 根据我的测试, 就算配置了 OpenSessionInViewFilter(前提: 不加事务), 也不会关闭这个Session. 也许有人说可以用连接池, 这种情况和Db pool没关系, 用了pool就会发现连接很快就会满, 只会over的更快. 反过来, 如果不配置OpenSessionInViewFilter, 在DAO里提前用 releaseSession()关闭连接, 就可能会在JSP中出现Lazy载入异常. 另一个不配事务的问题就是无法更新或者插入数据. 下面就是原始的JavaDoc中的说明:
/**
* Obtain a Hibernate Session, either from the current transaction or
* a new one. The latter is only allowed if the
* {@link org.springframework.orm.hibernate3.H