【问题标题】:Spring not releasing/reusing Hibernate sessions on JBoss EAP 6Spring 不在 JBoss EAP 6 上发布/重用 Hibernate 会话
【发布时间】:2014-07-03 09:31:52
【问题描述】:

我有一个使用 Hibernate 4 的 Spring 应用程序。Hibernate 配置位于我的 application-config.xml 中,如下所示:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
        </props>
    </property>
    <property name="packagesToScan">
        <list>
            <value>com.mycompany.esb.jpa</value>
        </list>
    </property>
</bean>

com.mycompany.esb.jpa 包中,我有以下类,该包中的所有其他类都是其子类。

package com.mycompany.esb.jpa.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class HibernateBaseDAO {

    @Autowired
    protected SessionFactory sessionFactory;

    protected Session getSession() {
        return sessionFactory.openSession();
    }

}

这是我为本示例简化的类之一。

package com.mycompany.esb.jpa.dao;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.springframework.stereotype.Component;

import com.mycompany.esb.jpa.entity.ServicesEntity;

@Component("servicesDAO")
public class ServicesDAOImpl extends HibernateBaseDAO implements ServicesDAO {

    @Override
    public List<ServicesEntity> getAllServices(double daysPrevious, double hoursToShow) {
        try {

            Query query = getSession().createQuery("FROM ServicesEntity e "
                    + "WHERE e.responseTime >= (sysdate - (" + daysPrevious + " + " + hoursToShow + "/24)) "
                    + "AND e.responseTime < (sysdate - " + daysPrevious + ") "
                    + "GROUP BY e.domainName, e.serviceName, e.operationName, e.elapsedTime, e.serviceTimestamp, "
                    + "e.id, e.responseTimeAverage, e.responseTime, e.requestSizeAverage, e.responseSizeAverage, e.requestCount "
                    + "ORDER BY e.domainName, e.serviceName, e.operationName, e.serviceTimestamp");

            @SuppressWarnings("unchecked")
            List<ServicesEntity> services = (List<ServicesEntity>) query.list();
            return services;

        } catch (HibernateException hex) {
            hex.printStackTrace();
        }
        return null;
    }
}

我遇到的问题是,当部署到 JBoss EAP 时,每次调用 getAllServices() 方法时,它都会从 JDBC 池中获取一个新连接并且永远不会释放它。因此,当容器 JDBC 池最多有 5 个连接时,在 5 次查询之后,后续查询会因为没有可用连接而超时。连接池不应该由 Hibernate SessionFactory 对象管理吗?我需要明确关闭连接吗?

【问题讨论】:

  • 为什么要这样做?您没有事务设置,然后您执行openSession 指示您想要管理自己的会话。设置事务并改用getCurrentSession

标签: spring hibernate jdbc jboss6.x


【解决方案1】:

正如用户 Orid 最初指出的那样:(他随后删除了他的答案)

那是因为你调用了 sessionFactory.openSession();里面 getSession() 在您的基类中,并且永远不会释放会话(并且 连接)通过调用 close()。

你应该使用 sessionFactory.getCurrentSession(); 根据您的情况将会话固定到 JTA 事务/线程 数据源事务资源管理配置。

此外,您应该使用注释 getAllServices @Transactional(readOnly=true) 用于正确的事务和连接 获取/发布管理。

我还必须将@EnableTransactionManagement 注释添加到我的ServicesDAOImpl 类并在JBoss EAP 中启用CCM。

所以我的新ServicesDAOImpl 课程如下:

package com.mycompany.esb.jpa.dao;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.springframework.stereotype.Component;

import com.mycompany.esb.jpa.entity.ServicesEntity;


@EnableTransactionManagement
@Component("servicesDAO")
public class ServicesDAOImpl extends HibernateBaseDAO implements ServicesDAO {

    @SuppressWarnings("unchecked")
    @Transactional(readOnly=true)
    @Override
    public List<ServicesEntity> getAllServices(double daysPrevious, double hoursToShow) {
        Query query = getSession().createQuery("FROM ServicesEntity e "
                + "WHERE e.responseTime >= (sysdate - (" + daysPrevious + " + " + hoursToShow + "/24)) "
                + "AND e.responseTime < (sysdate - " + daysPrevious + ") "
                + "GROUP BY e.domainName, e.serviceName, e.operationName, e.elapsedTime, e.serviceTimestamp, "
                + "e.id, e.responseTimeAverage, e.responseTime, e.requestSizeAverage, e.responseSizeAverage, e.requestCount "
                + "ORDER BY e.domainName, e.serviceName, e.operationName, e.serviceTimestamp");
        try {
            return (List<ServicesEntity>) query.list();
        } catch (HibernateException hex) {
            hex.printStackTrace();
        }
        return null;
    }
}

...我的新HibernateBaseDAO 课程如下:

package com.mycompany.esb.jpa.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class HibernateBaseDAO {

    @Autowired
    protected SessionFactory sessionFactory;

    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2013-07-23
    • 2019-03-30
    • 1970-01-01
    相关资源
    最近更新 更多