整合两个工程到一起,跑起来后,发现数据库连接玩命上升,一会就挂了,无法取得新连接了~~
用的druid连接池,配置web.xml,访问/druid查看数据源的连接数,
发现逻辑打开连接数,和逻辑关闭连接数,差了100多个,
页面执行查询一次,就差100多,
物理连接数也很多,100多,200多的,一直涨~~
说明连接没关闭,没回到池里,导致一直创建物理连接。 ------------------ debug代码,一点点试,执行某个查询后,就看连接数,
最后发现一个查询执行后,逻辑打开和关闭的差值就会增大,
说明这个查询打开连接后没有关闭,看代码,是大概这样的:
public class BaseDAO<T> extends HibernateDaoSupport{
@Override public void save(T t) { getHibernateTemplate().save(t); getHibernateTemplate().flush(); }
@Override public void merge(T t) { getHibernateTemplate().merge(t); // getHibernateTemplate().flush(); } .....
public Result hqlParam(String hql, HashMap map, Page page) { Query query = getSession().createQuery(hql); if (map != null) { query.setProperties(map); } String sum = ""; int fIndex = hql.indexOf("from"); if(fIndex!=-1){ sum = "select count(*) as count " + hql.substring(fIndex); } int oIndex = sum.indexOf("order by"); if(oIndex!=-1) { sum=sum.substring(0,oIndex); } Query querySum = getSession().createQuery(sum); if (map != null) { querySum.setProperties(map); } int count = ((Number) querySum.iterate().next()).intValue(); if (page == null) { query.setFirstResult(0); query.setMaxResults(count); } else { query.setFirstResult(page.getFirstResult()); query.setMaxResults(page.getPageSize());
} List<T> findByHql = query.list();
if (page == null) { return new Result(1, 1, count, findByHql, new ArrayList<Event>()); } else { return new Result(page.getPageNumber(), page.getPageSize(), count, findByHql, new ArrayList<Event>()); } } }
调用hqlParam方法的,就会有问题。
看到代码里的getSession,马上就感觉是这里的问题,
后面没有closeSession方法,
看getSession的说明:
打开声明 Session org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSession() throws DataAccessResourceFailureException, IllegalStateException
Obtain a Hibernate Session, either from the current transaction or a new one. The latter is only allowed if the "allowCreate" setting of this bean's HibernateTemplate is "true".
Note that this is not meant to be invoked from HibernateTemplate code but rather just in plain Hibernate code. Either rely on a thread-bound Session or use it in combination with releaseSession.
In general, it is recommended to use HibernateTemplate, either with the provided convenience operations or with a custom HibernateCallback that provides you with a Session to work on. HibernateTemplate will care for all resource management and for proper exception conversion.
看看,人家都说了,一般跟releaseSession配合使用。 一般建议使用HibernateCallback回调,它会自己管理session.
OK,改成这样了:
@Override public Result hqlParam(final String hql, final HashMap map, final Page page) {
// 用回调方法,它会自己管理session return (Result) this.getHibernateTemplate().execute(new HibernateCallback<Result>() { @Override public Result doInHibernate(Session session) throws HibernateException, SQLException {
Query query = session.createQuery(hql); if (map != null) { query.setProperties(map); } String sum = ""; int fIndex = hql.indexOf("from"); if (fIndex != -1) { sum = "select count(*) as count " + hql.substring(fIndex); } int oIndex = sum.indexOf("order by"); if (oIndex != -1) { sum = sum.substring(0, oIndex); } Query querySum = session.createQuery(sum); if (map != null) { querySum.setProperties(map); } int count = ((Number) querySum.iterate().next()).intValue(); if (page == null) { query.setFirstResult(0); query.setMaxResults(count); } else { query.setFirstResult(page.getFirstResult()); query.setMaxResults(page.getPageSize());
} List<T> findByHql = query.list();
if (page == null) { return new Result(1, 1, count, findByHql, new ArrayList<Event>()); } else { return new Result(page.getPageNumber(), page.getPageSize(), count, findByHql, new ArrayList<Event>()); } } }); }
编译,运行,问题解决~~
逻辑打开和逻辑关闭,一致了,物理连接数才2~~~
|