程序代码
public class DaoReal extends HibernateDaoSupport implements Dao {
public List<user> getAll() {
Session s = super.getSession();
try {
return s.createQuery("from User").list();
} finally {
s.close();
}
}
}
问题:(利用session.createQuery(...)方法的隐患)
上面的例子中隐藏了一个问题,数据库连接并没有被关闭,在我们的印象中这件事似乎应该是Spring的。程序执行后,好像也没有什么问题,但是连续执行该语句n次(n<=最大连接数,如果没有指定最大连接数,那么默认为10次)后,系统处于等待状态,不会继续执行了,控制台上并没有输出任何信息。打开log文件,发现系统抛出java.lang.IllegalStateException: Pool not open的异常,无法打开连接。这说明系统连接池中所有的连接都在使用中。
执行n遍后依然停止响应。问题出在哪里呢?其实Spring的Session总是与某个线程绑定的,而这个线程往往就是承载Servlet或Jsp的那个线程,也就是说,它的生命周期scope是request的。在上面的例子中,我们利用getSession强制获得了Hibernate的 Session,这个Session可能是当前事务中之前使用过的,或者可能是一个新的,并不在当前事务中,Spring只对当前事务中的Session 进行关闭。
请教大家有什么解决办法没? 还是我提的问题是错误的?谢谢大家?
问题补充
回楼上:
用到了hibernate+spring的话,一般我们直接用getHibernateTemplate().find("from User")这类型的查询。
单是现在我项目里面程序用到这个类型的:
Session s = super.getSession();
try {
return s.createQuery("from User").list();
} finally {
s.close();
}
我们测试中好像发现了这个session不能完全关闭好像。是不是这么回事??
问题补充
在使用Spring进行系统开发的时候,数据库连接一般都是配置在Spring的配置文件中,并且由Spring来管理的。在利用Spring + Hibernate进行开发时也是如此。
getHibernateTemplate().find("from User");
这类型的我们并没有关闭Session,但程序并没有任何问题,那是因为Spring已经帮我们关闭了。
问题补充:
getSession()是从当前的ThreadLocal中拿到的SESSION
就是说可以不用关闭SESSION,但这个线程结束的时候,SESSION就没了。。
但是我们的请求也许也许没有响应,一直在请求过程中,也是就是这个线程还没结束,那这个session也就没有关闭吧!
[code="java"]
Session s = super.getSession();
try {
return s.createQuery("from User").list();
} finally {
s.close();
}
[/code]你的这种写法是应该是没有什么问题的!不知道你的事务是怎么控制的!
建议还是使用getHibernateTemplate(), 如果一定要使用Session这种方式, 用HibernateTemplate可以这样使用:
[code="java"]
getHibernateTemplate().execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return session.createQuery("from User").list();
}
});
[/code]
spring的配置文件
好像不应该close session吧