【问题标题】:Connections checking in c3p0 poolc3p0 池中的连接检查
【发布时间】:2014-12-22 08:52:00
【问题描述】:

我正在开发 Java SE 应用程序,使用 Hibernate 4 和 c3p0 与 MariaDB 数据库进行通信。它是长时间运行的应用程序,等待来自外部的信号,因此有时数据库会在 8 小时不活动后关闭我的连接。我尝试配置 c3p0 连接验证,但它不工作。你能帮帮我吗?

错误日志(命名查询执行期间抛出):

2014-10-27 08:10:19.062 ERROR [trans] com.example.runnable.T1 - Exception thrown during event processing, rollbacking transaction: org.hibernate.exception.JDBCConnectionException: could not extract ResultSet
        at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:132)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:2065)
        at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)
        at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838)
        at org.hibernate.loader.Loader.doQuery(Loader.java:909)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
        at org.hibernate.loader.Loader.doList(Loader.java:2553)
        at org.hibernate.loader.Loader.doList(Loader.java:2539)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
        at org.hibernate.loader.Loader.list(Loader.java:2364)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
        at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)                                                                                                                                                    
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)                                                                                                                                                                    
        at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)                                                                                                                                                                         
        at com.example.runnable.T1.find(EventsTransmitter.java:140)                                                                                                                         
        at com.example.runnable.T1.run(EventsTransmitter.java:86)                                                                                                                                  
        at java.lang.Thread.run(Thread.java:745)                                                                                                                                                                                             
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 108,132,692 milliseconds ago.  The last packet sent successfully to the server was 108,132,692 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.                                                                                                                                                              
        at sun.reflect.GeneratedConstructorAccessor30.newInstance(Unknown Source)                                                                                                                                                            
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)                                                                                                                              
        at java.lang.reflect.Constructor.newInstance(Constructor.java:408)                                                                                                                                                                   
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:377)                                                                                                                                                                              
        at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1036)                                                                                                                                                         
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3661)                                                                                                                                                                                    
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2417)                                                                                                                                                                             
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582)                                                                                                                                                                          
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2530)                                                                                                                                                                   
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1907)                                                                                                                                                     
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2030)                                                                                                                                                        
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)                                                                                                                                       
        ... 17 more                                                                                                                                                                                                                          
Caused by: java.net.SocketException: Broken pipe                                                                                                                                                                                             
        at java.net.SocketOutputStream.socketWrite0(Native Method)                                                                                                                                                                           
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3643)
        ... 23 more

pom.xml:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.33</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.3.6.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.1.2.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>4.3.6.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-c3p0</artifactId>
    <version>4.3.6.Final</version>
</dependency>

src/main/resources/hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/MyBase?zeroDateTimeBehavior=convertToNull&amp;autoReconnect=true</property>
    <property name="hibernate.connection.username">user</property>
    <property name="hibernate.connection.password">pass</property>

    <property name="hibernate.current_session_context_class">thread</property>

    <property name="show_sql">true</property>
    <property name="use_sql_comments">true</property>

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">10</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">30</property>

    <mapping class="com.example.domain.E" />
    </session-factory>
</hibernate-configuration>

src/main/resources/c3p0-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
    <property name="preferredTestQuery">SELECT 1 FROM DUAL</property>
    <property name="testConnectionOnCheckin">true</property>
    <property name="idleConnectionTestPeriod">1800</property> <!-- 30 minutes -->
    </default-config>
</c3p0-config>

已编辑

在启动日志中,我得到 c3p0 配置(由 Netbeans 的 Maven 执行):

...
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@81187ff9
[ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@e1820e10 [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000,
autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null,
connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null,
forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt95n558v5xddgsj|2cf3d63b, idleConnectionTestPeriod -> 1800, initialPoolSize -> 5,
maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 30,
maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@2f0d7eae [ description -> null, driverClass -> null,
factoryClassLocation -> null, identityToken -> z8kflt95n558v5xddgsj|1e6a3214, jdbcUrl -> jdbc:mysql://localhost:3306/MyBase?zeroDateTimeBehavior=convertToNull&autoReconnect=true,
properties -> {user=******, password=******} ], preferredTestQuery -> SELECT 1 FROM DUAL, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0,
testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ],
dataSourceName -> null, factoryClassLocation -> null, identityToken -> z8kflt95n558v5xddgsj|7161d8d1, numHelperThreads -> 3 ]
...

编辑 2

当执行由 maven-shade-plugin 创建的 jar 时,我得到:

2014 年 2 月 27 日晚上 10:56:22 org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator instanceC3p0Provider WARN: HHH000022: c3p0 属性是 遇到过,但在 类路径;这些属性将被忽略。 2014 年 2 月 27 日以后 晚上 10:56:22 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl 配置 WARN: HHH000402: Using Hibernate built-in connection pool (不用于生产!) paź 27, 2014 10:56:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl 生成器

或者当我试图在属性中指出org.hibernate.connection.C3P0ConnectionProvider 时:

信息:HHH000130:实例化显式连接提供程序: org.hibernate.connection.C3P0ConnectionProvider 初始会话工厂 创建 failed.org.hibernate.service.spi.ServiceException:无法 创建请求的服务 [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] 线程“主”java.lang.ExceptionInInitializerError 中的异常 在 com.example.util.HibernateUtil.(HibernateUtil.java:27) 在 com.example.App.run(App.java:31) 在 com.example.App.main(App.java:25)
引起:org.hibernate.service.spi.ServiceException:无法 创建请求的服务 [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]

    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:261)

    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:225)

    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)

    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)

    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)

    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)

    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)

    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)

    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)

    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)

    at com.example.util.HibernateUtil.<clinit>(HibernateUtil.java:24)

    ... 2 more                                                                                                                                                                                                                Caused by: org.hibernate.HibernateException: Could not instantiate

连接提供者 [org.hibernate.connection.C3P0ConnectionProvider]

    at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.instantiateExplicitConnectionProvider(ConnectionProviderInitiator.java:197)

    at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:120)
    at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:55)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:105)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:251)
    ... 12 more Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException:

无法解析名称 [org.hibernate.connection.C3P0ConnectionProvider] 作为策略 [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] 在 org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:128) 在 org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.instantiateExplicitConnectionProvider(ConnectionProviderInitiator.java:194) ... 16 更多

但是从 Maven 开始一切都很好。不幸的是,我需要这个从单个 jar 中工作。为什么在阴影 jar 中找不到 org.hibernate.connection.C3P0ConnectionProvider 的任何想法?

【问题讨论】:

    标签: java hibernate c3p0 socketexception


    【解决方案1】:

    尝试在您的 c3p0-config 中将 testConnectionOnCheckout 设置为 true。

    【讨论】:

      【解决方案2】:

      您确定 c3p0 已实际初始化,并且具有您期望的配置吗?

      在您的日志中,在 INFO 级别,您应该会在池初始化时看到 c3p0 数据源配置的转储。验证它是否存在,并且是您期望的配置。

      如果不存在,请考虑将以下行添加到您的 hibernate.cfg.xml:

      <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" /> 
      

      【讨论】:

      • 你是对的,当我从控制台执行我的胖 jar 时,c3p0 没有初始化 - 请参阅更新的问题。我发现在 hibernate-c3p0 包 v4.3.6 中没有 org.hibernate.connection.C3P0ConnectionProvider 类,但是有 org.hibernate.c3p0.internal.C3P0ConnectionProvider 。我用了它,它看起来不错,c3p0 已初始化,我只是在等待检查连接检查问题是否已解决。
      【解决方案3】:

      好的,我设法解决了所有问题。这是灵魂。

      首先,正如 Steve Waldman 所建议的,c3p0 实际上并没有被初始化,但在 Hibernate 4.3 中,hibernate.connection.provider_class 参数应该是:org.hibernate.c3p0.internal.C3P0ConnectionProvider。在documentation 你可以阅读:

      使用 C3P0 连接池的连接提供程序。冬眠会 如果设置了 hibernate.c3p0.* 属性,则默认使用它。

      但在我看来,这个参数最好自己放,如果你使用的是 c3p0 配置文件,而不是hibernate.c3p0.* 属性,则需要它。


      第二个问题是通过在线程开始时调用SessionFactory.openSession() 来获取会话,然后总是使用相同的会话对象。我想在数据库连接断开并且在池中重新创建一个新的连接之后,使用旧会话导致使用旧的断开连接。因此,可能的解决方案是在捕获连接错误后通过SessionFactory.openSession() 获取新会话,或者在每次通信开始时使用SessionFactory.getCurrentSession()。我决定使用第二个选项(在这种情况下,我的应用程序会等待外部信号,有时会等待数小时,因此我会在每个信号后获取当前会话)。


      我的最终配置:

      hibernate.cfg.xml:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
      <hibernate-configuration>
          <session-factory>
          <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
          <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
          <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/MyBase?zeroDateTimeBehavior=convertToNull&amp;autoReconnect=true</property>
          <property name="hibernate.connection.username">user</property>
          <property name="hibernate.connection.password">pass</property>
          <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
      
          <property name="hibernate.current_session_context_class">thread</property>
      
          <property name="show_sql">true</property>
          <property name="use_sql_comments">true</property>
      
          <property name="hibernate.cache.use_second_level_cache">true</property>
          <property name="hibernate.cache.use_query_cache">true</property>
          <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
          </session-factory>
      </hibernate-configuration>
      

      c3p0-config.xml:

      <?xml version="1.0" encoding="UTF-8"?>
      <c3p0-config>
          <default-config>
          <property name="initialPoolSize">5</property>
          <property name="minPoolSize">5</property>
          <property name="maxPoolSize">10</property>
          <property name="checkoutTimeout">3000</property>
          <property name="maxStatementsPerConnection">30</property>
      
          <property name="preferredTestQuery">SELECT 1 FROM DUAL</property>
          <property name="testConnectionOnCheckin">true</property>
          <property name="testConnectionOnCheckout">false</property>
          <property name="idleConnectionTestPeriod">300</property> <!-- 5 minutes -->
          </default-config>
      </c3p0-config>
      

      使用此 c3p0 配置:

      • 每 5 分钟未对连接执行任何查询都会对其进行测试,因此它永远不会被 DB 失效(在标准配置中,MySQL 会在 8 小时不活动后使连接失效),
      • 如果要重新启动数据库或手动终止连接,我们有两个选择: a) 最多 5 分钟后将重新建立连接, b) 如果应用程序在自动重新建立连接之前尝试执行查询HibernateException将被抛出,那么连接将被重新建立,下一次查询将成功。

      testConnectionOnCheckout 可选设置为 true 以防止异常,但会导致性能问题(请参阅documentation)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-20
        • 2011-01-07
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-09
        • 1970-01-01
        相关资源
        最近更新 更多