Spring与Hibernate的整合所遇到的管理Session的问题
2012-04-26 11:35
447 查看
转自:http://www.zzz8.com/thread-2387024-1-1.html
最近使用Struts1.3+Spring2.0+Hibernate3.2做了一个项目,最后测试时发现一个致命的错误,我的项目运行一段时间后,数据库直接down掉了。
While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30)。
(报错信息意思为超出最大连接数,不能打开连接。补充:我的异常信息和这类似,待找到会贴上来。)
这个错误郁闷了我很久,通过大家的帮助还有网络的大量资源我终于找到了其中的原因。首先说说我的daoimpl的写法,在daoimpl中我使用
Java code Query q = super.getSession().createQuery(hql);
语句可以正常执行,但是在多次使用该语句后数据库有很多连接仍然没有断开!这是导致异常的关键所在,spring不是管理了session吗?这是为什么呢?
通过继承HibernateDaoSupport我们有两个选择:
Java code getSession().createQuery("from Users");
getHibernateTemplate().find( "FROM Users);
网上找了找资料都是推荐用getHibernateTemplate,原因说的不是很清楚。
于是我做了如下测试:
分别循环调用getSession().createQuery("from Users");getHibernateTemplate().find( "FROM Users);
1000次
结果getSession()很快就包无法建立连接了。而getHibernateTemplate屁事没有可以跑完。
通过后台观察,使用getSession会在数据库中留下很多SQL*Net message from client的连接,终止测试后连接自动释放。
而getHibernateTemplate则从头到尾都使用一个连接。
难道是getSession()不会自动释放连接?
于是我又分别循环调用getSession().createQuery("from Users");getHibernateTemplate().find( "FROM Users);
5次
发现当前端程序一结束,getSession的5个连接立刻就释放了。结合前面1000次时终止测试后连接自动释放,可以说明getSession()是会自动释放连接的。
结论:
1、getSession()和getHibernateTemplate都可以自动释放连接(当然你的配置要正确),但是在一个线程内getSession会get很多个session(就是开很多个会话、连接),很可能导致数据库连接超过上限。所以推荐使用getHibernateTemplate。
2、如果有些语句无法用getHibernateTemplate实现,可以使用getHibernateTemplate.execute使用HibernateCallback回调接口。
(补充:之前项目中有遇到这个问题
bug如下:
org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Cannot open connection
org.hibernate.exception.GenericJDBCException: Cannot open connection
Caused by: java.sql.SQLException: org.logicalcobwebs.proxool.ProxoolException: ConnectionCount is 15. Maximum connection count of 15 cannot be exceeded.
,发现这篇文章分析的不错,所以就转载过来了;之前通过上网查资料,发现貌似OpenSessionInView模式这种貌似也可以控制session释放,但是网上说的方法我经过测试没有成功,网址如下:http://kewb.javaeye.com/blog/128726 按照配置去做,总是会报异常,配置成功的可以联系我,谢谢!)
另:可以设定HibernateTemplate的AllowCreate为True,并在finally中关闭Session。也可以将true作为参数传递到super.getSession(..)方法中取得Session。这样也可以,就是麻烦点。
参见:
http://springframework.org/docs/api/org/springframework/orm/hibernate3/HibernateTemplate.html http://www.mxjava.com/blog/article.asp?id=246
参考资料:http://blog.sina.com.cn/s/blog_50e4caf70100a1nx.html
于是,如果我们一定要书写hql语句可以参考如下形式
Java code public PageUtil getLog(final Long userid,final Integer page) {
String counthql="select count(mod) from Blog mod where mod.userinfo.userid=?";
Integer count=(Integer)getHibernateTemplate().find(counthql, userid).get(0);
final PageUtil pu=new PageUtil();// 分页包装类
pu.setCount(count);
pu.setPage(page);
pu.setMaxPagesbyCount(count);
List li= getHibernateTemplate().executeFind(new HibernateCallback(){7
public Object doInHibernate(Session session) throws HibernateException, SQLException {
String hql="from Blog mod left join fetch mod.userinfo where mod.userinfo.userid=? order by mod.logid desc";
Query query=session.createQuery(hql);
query.setParameter(0, userid);
query.setMaxResults(pu.getMaxResults());
query.setFirstResult(pu.getFirstResult());
return query.list();.
}
});
pu.setResults(li);;
return pu ;(
}; ~3
只有这样做了以后才能确保数据库的连接能够尽早被释放,项目不至于崩溃。
补充上回调函数调用存储过程方式:
public class ExecuteProceduresDaoImpl extends JdbcDaoSupport implements ExecuteProceduresDao {
public Object Call_prLS_OrderByMemberOrNotMember(final String[] parm) {
String procedureSql = "{?=call prLS_OrderByMemberOrNotMember(?,?,?,?,?,?,?,?,?,?)}";
return (Object) getJdbcTemplate().execute(procedureSql, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
int j = 2;
cs.registerOutParameter(1, Types.INTEGER);
if (parm != null) {
for (int i = 0; i < parm.length; i++) {
cs.setString(j, parm[i]);
++j;
}
}
if (cs.execute()) {
ResultSet rs = cs.getResultSet();
while (rs.next()) {
rs.getString(1);
rs.getString(2);
rs.getString(3);
}
return null;
} else {
return cs.getInt(1);
}
}
});
}
}
最近使用Struts1.3+Spring2.0+Hibernate3.2做了一个项目,最后测试时发现一个致命的错误,我的项目运行一段时间后,数据库直接down掉了。
While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30)。
(报错信息意思为超出最大连接数,不能打开连接。补充:我的异常信息和这类似,待找到会贴上来。)
这个错误郁闷了我很久,通过大家的帮助还有网络的大量资源我终于找到了其中的原因。首先说说我的daoimpl的写法,在daoimpl中我使用
Java code Query q = super.getSession().createQuery(hql);
语句可以正常执行,但是在多次使用该语句后数据库有很多连接仍然没有断开!这是导致异常的关键所在,spring不是管理了session吗?这是为什么呢?
通过继承HibernateDaoSupport我们有两个选择:
Java code getSession().createQuery("from Users");
getHibernateTemplate().find( "FROM Users);
网上找了找资料都是推荐用getHibernateTemplate,原因说的不是很清楚。
于是我做了如下测试:
分别循环调用getSession().createQuery("from Users");getHibernateTemplate().find( "FROM Users);
1000次
结果getSession()很快就包无法建立连接了。而getHibernateTemplate屁事没有可以跑完。
通过后台观察,使用getSession会在数据库中留下很多SQL*Net message from client的连接,终止测试后连接自动释放。
而getHibernateTemplate则从头到尾都使用一个连接。
难道是getSession()不会自动释放连接?
于是我又分别循环调用getSession().createQuery("from Users");getHibernateTemplate().find( "FROM Users);
5次
发现当前端程序一结束,getSession的5个连接立刻就释放了。结合前面1000次时终止测试后连接自动释放,可以说明getSession()是会自动释放连接的。
结论:
1、getSession()和getHibernateTemplate都可以自动释放连接(当然你的配置要正确),但是在一个线程内getSession会get很多个session(就是开很多个会话、连接),很可能导致数据库连接超过上限。所以推荐使用getHibernateTemplate。
2、如果有些语句无法用getHibernateTemplate实现,可以使用getHibernateTemplate.execute使用HibernateCallback回调接口。
(补充:之前项目中有遇到这个问题
bug如下:
org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Cannot open connection
org.hibernate.exception.GenericJDBCException: Cannot open connection
Caused by: java.sql.SQLException: org.logicalcobwebs.proxool.ProxoolException: ConnectionCount is 15. Maximum connection count of 15 cannot be exceeded.
,发现这篇文章分析的不错,所以就转载过来了;之前通过上网查资料,发现貌似OpenSessionInView模式这种貌似也可以控制session释放,但是网上说的方法我经过测试没有成功,网址如下:http://kewb.javaeye.com/blog/128726 按照配置去做,总是会报异常,配置成功的可以联系我,谢谢!)
另:可以设定HibernateTemplate的AllowCreate为True,并在finally中关闭Session。也可以将true作为参数传递到super.getSession(..)方法中取得Session。这样也可以,就是麻烦点。
参见:
http://springframework.org/docs/api/org/springframework/orm/hibernate3/HibernateTemplate.html http://www.mxjava.com/blog/article.asp?id=246
参考资料:http://blog.sina.com.cn/s/blog_50e4caf70100a1nx.html
于是,如果我们一定要书写hql语句可以参考如下形式
Java code public PageUtil getLog(final Long userid,final Integer page) {
String counthql="select count(mod) from Blog mod where mod.userinfo.userid=?";
Integer count=(Integer)getHibernateTemplate().find(counthql, userid).get(0);
final PageUtil pu=new PageUtil();// 分页包装类
pu.setCount(count);
pu.setPage(page);
pu.setMaxPagesbyCount(count);
List li= getHibernateTemplate().executeFind(new HibernateCallback(){7
public Object doInHibernate(Session session) throws HibernateException, SQLException {
String hql="from Blog mod left join fetch mod.userinfo where mod.userinfo.userid=? order by mod.logid desc";
Query query=session.createQuery(hql);
query.setParameter(0, userid);
query.setMaxResults(pu.getMaxResults());
query.setFirstResult(pu.getFirstResult());
return query.list();.
}
});
pu.setResults(li);;
return pu ;(
}; ~3
只有这样做了以后才能确保数据库的连接能够尽早被释放,项目不至于崩溃。
补充上回调函数调用存储过程方式:
public class ExecuteProceduresDaoImpl extends JdbcDaoSupport implements ExecuteProceduresDao {
public Object Call_prLS_OrderByMemberOrNotMember(final String[] parm) {
String procedureSql = "{?=call prLS_OrderByMemberOrNotMember(?,?,?,?,?,?,?,?,?,?)}";
return (Object) getJdbcTemplate().execute(procedureSql, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
int j = 2;
cs.registerOutParameter(1, Types.INTEGER);
if (parm != null) {
for (int i = 0; i < parm.length; i++) {
cs.setString(j, parm[i]);
++j;
}
}
if (cs.execute()) {
ResultSet rs = cs.getResultSet();
while (rs.next()) {
rs.getString(1);
rs.getString(2);
rs.getString(3);
}
return null;
} else {
return cs.getInt(1);
}
}
});
}
}
相关文章推荐
- Spring与Hibernate的整合所遇到的管理Session的问题
- 探讨Spring与Hibernate的整合所遇到的管理Session的问题
- 探讨Spring与Hibernate的整合所遇到的管理Session的问题
- id to load is required for loading 对Struts,Hibernate,Spring整合开发中遇到问题
- spring和hibernate整合遇到的问题
- hibernate整合spring开发的时候遇到的一些小问题
- struts2+hibernate+spring整合过程中遇到的问题
- hibernate整合到spring上遇到的一个问题
- (10)Spring和Hibernate整合过程中遇到的问题
- Spring整合Hibernate遇到的问题
- Spring 3.x 与Hibernate 4.x 整合遇到的问题
- Spring整合hibernate(注解)遇到unknown entity问题
- flex 整合spring,hibernate遇到的一些问题
- id to load is required for loading 对Struts,Hibernate,Spring整合开发中遇到问题
- Spring 与 hibernate 整合遇到的问题
- hibernate与spring整合所遇到的问题
- hibernate4 和 spring3 整合注意事项:HibernateDaoSupport没有了找到篇好文章,我之前遇到的问题都在这都能找到。其实出现这些问题的关键就是hibernate4和hib
- 解决问题(八)——jsf+spring+hibernate整合(二)
- Spring+SpringMVC+Mybatis整合,你可能遇到的问题
- Hibernate4与spring整合找不到org.hibernate.cache.CacheProvider问题