2014-10-27 154 views
5

我正在开发Java SE应用程序,使用Hibernate 4和c3p0与MariaDB数据库进行通信。它是长时间运行的应用程序,等待来自外部的信号,所以有时数据库会在闲置8小时后关闭我的连接。我试图配置c3p0连接验证,但它不起作用。你可以帮帮我吗?在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 /主/资源/ 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... [email protected] 
[ connectionPoolDataSource -> [email protected] [ 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 -> [email protected] [ 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时,我得到:

PAZ 27 2014年下午10点56分22秒 org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator instantiateC3p0Provider警告:HHH000022:C3P0性能 遇到,但C3P0提供者类没有被发现类路径 ;这些属性将被忽略。 paź27,2014 10:56:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl 配置WARN:HHH000402:使用Hibernate内置连接池 (不适合生产使用!)paź27,2014下午10时56分22秒 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator

或者当我试图表明性能org.hibernate.connection.C3P0ConnectionProvider

信息:HHH000130:明确的实例化连接p rovider: org.hibernate.connection.C3P0ConnectionProvider初始会话工厂 创建failed.org.hibernate.service.spi.ServiceException:无法 创建请求的服务 [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] 异常在线程“main”java.lang.ExceptionInInitializerError at com.example.util.HibernateUtil。(HibernateUtil.java:27) at com.example.App.run(App.java:31) at 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] at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:128) at org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator .instantiateExplicitConnectionProvider(ConnectionProviderInitiator.java:194) ...... 16多个

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

回答

4

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

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

使用C3P0连接池的连接提供程序。如果设置了hibernate.c3p0。*属性,Hibernate将默认使用 。

但在我看来这是很好的自己把这个参数,它如果您正在使用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分钟不进行上连接的任何查询它将被测试的,所以它将永远不会被数据库无效(在标准配置中MySQL在8小时不活动状态下使连接无效),
  • 如果数据库将被重新启动或连接无线b)如果应用程序在自动连接重建之前尝试执行查询,将会重新建立HibernateException,则将重新建立连接,并且下一个查询将成功。

可以将testConnectionOnCheckout设置为true以防止出现异常,但会引起性能问题(请参阅documentation)。

0

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

0

你确定c3p0实际上是初始化的,并且它有你期望的配置吗?

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

,如果它不存在,请考虑增加以下行把hibernate.cfg.xml:

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

你说得对,当我从控制台执行我的fat jar时,c3p0没有初始化 - 查看更新后的问题。我发现在hibernate-c3p0软件包v4.3.6中没有org.hibernate.connection.C3P0ConnectionProvider类,而是有org.hibernate.c3p0.internal.C3P0ConnectionProvider。我用它,它看起来不错,c3p0已初始化,我只是在等待检查连接检查问题是否解决。 – Radzikowski 2014-10-27 22:42:10