【问题标题】:Connection pooling Hibernate连接池休眠
【发布时间】:2016-07-15 05:17:24
【问题描述】:

我有一个带有 Hibernate 的 Java 应用程序。我只是实现它c3p0。 Aperentemente 一开始一切正常(只要我在我们的主机中重新启动 Tomcat 服务器)。但是在几次客户访问后不久,它碰巧没有创建更多的会话来与我们的 BD mysql 交互。 谁可以帮我这个事?我将不胜感激。

以下代码:

Hibernate.cfg.xml:

<property name="hibernate.connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider
</property>
<property name="hibernate.c3p0.min_size">7</property>
<property name="hibernate.c3p0.max_size">53</property>
<property name="hibernate.c3p0.timeout">100</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">1000</property>
<property name="hibernate.c3p0.validate">true</property>

HibernateUtil.java:

public final class HibernateUtil{  
     private static SessionFactory sessionFactory;  
        public static SessionFactory getSessionFactory()  throws MappingException  
        {  
            if(sessionFactory == null) {
                //sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
                sessionFactory = new Configuration().configure().buildSessionFactory();
            }  
            return sessionFactory;  
        } 

        public static Session openSession()  
        {  
            return getSessionFactory().openSession();  
        }  

}

CidadesDao.java:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.hibernate.type.StandardBasicTypes;
import ConnectionHibernate.ConnectionHibernate;
import ConnectionHibernate.HibernateUtil;
import br.com.cuponero.bean.Cidades;

public class CidadesDao {
    private static final String TABLE = "Cidades";
    Session session;

    public CidadesDao() {
        this.session = HibernateUtil.getSessionFactory().openSession();
        this.session.beginTransaction();
    }

    /**
     * Select todos
     * @return 
     **/
    public List<Cidades> getTodos(){
          List<Cidades> lCit = null;

          try{
             Query q = session.createSQLQuery("SELECT * FROM "+TABLE)
                     .addScalar("id", StandardBasicTypes.BIG_INTEGER)
                     .addScalar("nome", StandardBasicTypes.STRING)
                     .addScalar("ddd", StandardBasicTypes.STRING)
                     .addScalar("estaoId", StandardBasicTypes.INTEGER)
                     .addScalar("ativo", StandardBasicTypes.INTEGER)

                     .setResultTransformer(Transformers.aliasToBean(Cidades.class));
             //System.out.println("list 0: "+q.list().get(0));

             lCit = q.list();
             //tx.commit();

          }catch (HibernateException e) {
             if (session!=null) session.beginTransaction().rollback();
             e.printStackTrace(); 
          }finally{
              //closeMyConnection();
              //mySessionClose();

              session.beginTransaction().commit();
          }

          return lCit;
    }

...

在记录此 Web 服务之后:

2016 年 3 月 27 日下午 4:30:32 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask 运行 广告:com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@172ea03 -- 获取尝试失败!!!清除挂起的获取。在尝试获取所需的新资源时,我们未能成功超过允许的最大获取尝试次数 (30)。上次获取尝试异常: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 用户 cupone_plinhares 已经有超过 'max_user_connections' 的活动连接 在 sun.reflect.GeneratedConstructorAccessor28.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.Util.getInstance(Util.java:387) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:871) 在 com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1686) 在 com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207) 在 com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2254) 在 com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2285) 在 com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2084) 在 com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:795) 在 com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44) 在 sun.reflect.GeneratedConstructorAccessor23.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:400) 在 com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:327) 在 com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184) 在 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess (BasicResourcePool.java:1073) 在 com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44) 在 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810) 在 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)

2016 年 3 月 27 日下午 4:30:32 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask 运行 广告:com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@3ba80 -- 获取尝试失败!!!清除挂起的获取。在尝试获取所需的新资源时,我们未能成功超过允许的最大获取尝试次数 (30)。上次获取尝试异常: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 用户 cupone_plinhares 已经有超过 'max_user_connections' 的活动连接 在 sun.reflect.GeneratedConstructorAccessor28.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.Util.getInstance(Util.java:387) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:871) 在 com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1686) 在 com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207) 在 com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2254) 在 com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2285) 在 com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2084) 在 com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:795) 在 com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44) 在 sun.reflect.GeneratedConstructorAccessor23.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:400) 在 com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:327) 在 com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184) 在 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess (BasicResourcePool.java:1073) 在 com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44) 在 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810) 在 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)

2016 年 3 月 27 日下午 4:30:32 com.mchange.v2.resourcepool.BasicResourcePool forceKillAcquires ADVERTÊNCIA:在获取资源失败后,com.mchange.v2.resourcepool.BasicResourcePool@16df536 正在中断所有等待资源检查的线程。将再次尝试响应新的客户端请求。 2016 年 3 月 27 日下午 4:30:32 com.mchange.v2.resourcepool.BasicResourcePool forceKillAcquires ADVERTÊNCIA:在获取资源失败后,com.mchange.v2.resourcepool.BasicResourcePool@16df536 正在中断所有等待资源检查的线程。将再次尝试响应新的客户端请求。 2016 年 3 月 27 日下午 4:30:32 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 警告:SQL 错误:0,SQLState:空 2016 年 3 月 27 日下午 4:30:32 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 错误:无法从底层数据库获取连接! 2016 年 3 月 27 日下午 4:30:32 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask 运行 广告:com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@2386af -- 获取尝试失败!!!清除挂起的获取。在尝试获取所需的新资源时,我们未能成功超过允许的最大获取尝试次数 (30)。上次获取尝试异常: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 用户 cupone_plinhares 已经有超过 'max_user_connections' 的活动连接 在 sun.reflect.GeneratedConstructorAccessor28.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.Util.getInstance(Util.java:387) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806) 在 com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:871) 在 com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1686) 在 com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207) 在 com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2254) 在 com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2285) 在 com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2084) 在 com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:795) 在 com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44) 在 sun.reflect.GeneratedConstructorAccessor23.newInstance(未知来源) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 在 com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:400) 在 com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:327) 在 com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195) 在 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184) 在 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086) 在 com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess (BasicResourcePool.java:1073) 在 com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44) 在 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810) 在 com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)

为了获得最佳帮助,当我尝试连接此 Web Service UP 时,在我的应用程序的 Android Studio 中登录:

org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:90) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:112) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:230) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:237) org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:213) org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52) org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1454) br.com.cuponero.dao.CidadesDao.(CidadesDao.java:31) br.com.cuponero.actionsDaServlet.CidadesActionDaServlet.getJsonRegiao(CidadesActionDaServlet.java:35) br.com.cuponero.servlet.CidadesServlet.doPost(CidadesServlet.java:69) javax.servlet.http.HttpServlet.service(HttpServlet.java:650) javax.servlet.http.HttpServlet.service(HttpServlet.java:731) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

根本原因 java.sql.SQLException:无法从底层数据库获取连接! com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:689) com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140) org.hibernate.c3p0.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:73) org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:382) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:87) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:112) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:230) org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:237) org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:213) org.hibernate.engine。

看到她说问题出在这条日志行: br.com.cuponero.dao.CidadesDao。

this.session.beginTransaction();

【问题讨论】:

  • 问题:您有多少个 CidadesDao 实例?是单身人士吗?还有多少 DAO 连接到数据库?为什么要在 DAO 构造函数中创建会话 - 你在所有 DAO 中都这样做吗?
  • 所以我还有 4 个类似的类 dao,它们也有相同的逻辑来实例化这些会话。你有什么建议?
  • 建议是在方法中创建一个会话,而不是像史蒂夫建议的那样将其作为成员变量维护。我要求提供类和实例,因为我想知道连接耗尽的原因。如果每个实例都使用池中的连接并且不返回它,它们将被耗尽。我想知道计数。

标签: hibernate connection c3p0 pooling


【解决方案1】:

所以这直接来自您的堆栈跟踪:

用户 cupone_plinhares 已经有超过 'max_user_connections' 个活动连接

一个显而易见的尝试是 increase max_user_connection 用户 cupone_plinhares

在查看您的堆栈跟踪之前,我认为问题将是连接泄漏。您的 DAO 在其构造函数中创建了一个休眠会话作为成员变量,似乎没有任何东西可以关闭它。此外,您的事务管理看起来很可疑。

一个更好的主意是根本不将session 作为成员变量,而是使用类似的东西

Session session = null;
Transaction txn = null;
try {
  session = HibernateUtil.getSessionFactory().openSession();
  txn = session.beginTransaction();

  //do important stuff here

  txn.commit()
} catch ( Exception e ) {
  try { if (txn != null) txn.rollback() }
  catch (HibernateException he) { 
    he.printStackTrace(); 
    e.addSuppressed( he );
    throw e;
  }
} finally {
  try { if (session != null) session.close() }
  catch (SQLException sqle) { sqle.printStackTrace(); }
}

您可以以不同于打印到标准错误的方式记录事情,或者在txn.rollback() 失败时对传播哪个异常做出不同的决定。但是您需要开始/提交/回滚一致的事务,并且您应该根据需要创建会话并及时销毁它们,而不是在生命周期不确定的成员变量中保持打开状态。

连接池的意义在于降低会话创建成本,因此您不必处理管理持久会话的复杂性。

【讨论】:

  • 然后,我将使用 Transition 的实例而不是 Session 进行测试,就像我正在做的那样。但解决我的问题的一件事是在屏幕上打印银行的任何结果后关闭 Session Dao。 ... out.print ("银行结果"); myInstanceDao.closeMySessions();在我的方法 I 中: public void closeMySessions () { session.beginTransaction () commit ().; session.close();但是我的应用程序仍然在消耗大量内存,我相信这与它有关。谁能继续帮忙,谢谢。
猜你喜欢
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 1970-01-01
  • 2013-12-29
相关资源
最近更新 更多