[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]spring+hibernate里,getSession没关闭导致的连接泄漏~~

上一篇:[备忘]多个数据源时的OpenSessionInViewFilter,与延迟加载lazy
下一篇:[转帖]Spring/Hibernate: Multiple Datasources

添加日期:2015/1/9 17:35:43 快速返回   返回列表 阅读6324次
整合两个工程到一起,跑起来后,发现数据库连接玩命上升,一会就挂了,无法取得新连接了~~

用的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~~~
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved