2014-10-27 18 views
5

Sto sviluppando con l'applicazione Java SE utilizzando Hibernate 4 e c3p0 per la comunicazione con il database MariaDB. È un'applicazione di lunga durata, in attesa di segnali dall'esterno, quindi a volte il database chiude le mie connessioni dopo 8 ore di inattività. Ho provato a configurare le connessioni c3p0 validando ma non funziona. Potresti aiutarmi?Controllo connessioni nel pool c3p0

log di errore (generata durante l'esecuzione di query di nome):

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/risorse/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> 

Redatta

In accede all'avvio mi sto configurazione c3p0 (esecuzione con Maven da Netbeans):

... 
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 ] 
... 

Edit 2

Durante l'esecuzione di jar creato da maven-shade-plug, sto ricevendo:

Paz 27, 2014 22:56:22 org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator instantiateC3p0Provider avvertono: HHH000022: proprietà c3p0 sono stati incontrati, ma la classe fornitore c3p0 non è stato trovato su il classpath ; queste proprietà saranno ignorate. Paz 27 2014 22:56:22 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configurare avvertono: HHH000402: usando Hibernate built-in pool di connessioni (! non per l'uso in produzione) Paz 27, 2014 22:56:22 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator

o quando ho cercato di indicare org.hibernate.connection.C3P0ConnectionProvider nelle proprietà:

INFORMAZIONI: HHH000130: Instantiating esplicito connessione p rovider: org.hibernate.connection.C3P0ConnectionProvider SessionFactory iniziale creazione failed.org.hibernate.service.spi.ServiceException: Impossibile creare il servizio richiesto [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] Eccezione nella discussione "main" java.lang.ExceptionInInitializerError su com.example.util.HibernateUtil. (HibernateUtil.java:27) su com.example.App.run (App.java:31) su com.example.App .main (App.java:25)
Causato da: org.hibernate.service.spi.ServiceException: impossibile a creare il servizio richiesto [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 

provider di connessione [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: 

Impossibile risolvere il nome [org.hibernate.connection.C3P0ConnectionProvider] come strategia [org.hibernate.engine .jdbc.connections.spi.ConnectionProvider] in org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor (StrategySelectorImpl.java:128) presso org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator .instantiateExplicitConnectionProvider (ConnectionProviderInitiator.java:194) ... altri 16

Ma tutto è buono quando si inizia da Maven. Purtroppo ho bisogno di questo per funzionare da un singolo barattolo. Qualche idea per cui org.hibernate.connection.C3P0ConnectionProvider non può essere trovato nel barattolo ombreggiato?

risposta

4

Ok, sono riuscito a risolvere tutti i problemi. Ecco l'anima.

Prima di tutto, come suggerito da Steve Waldman, c3p0 non è stato effettivamente inizializzato, ma in Hibernate 4.3 il parametro hibernate.connection.provider_class deve essere: org.hibernate.c3p0.internal.C3P0ConnectionProvider. In documentation è possibile leggere:

Un provider di connessione che utilizza un pool di connessioni C3P0. Hibernate lo utilizzerà per impostazione predefinita se sono impostate le proprietà hibernate.c3p0. *.

Ma a mio parere è bene mettere questo parametro da soli, ed è necessario se si utilizza il file di configurazione c3p0, non hibernate.c3p0.* proprietà.


Secondo problema era ottenere sessione chiamando SessionFactory.openSession() all'inizio del filo e in seguito utilizzando sempre lo stesso oggetto sessione. Suppongo che dopo la connessione al database sia stata interrotta e ne sia stata ricreata una nuova nel pool, utilizzando la vecchia sessione causata dall'utilizzo di una connessione vecchia e interrotta. Quindi le possibili soluzioni stavano ottenendo una nuova sessione entro il SessionFactory.openSession() dopo aver rilevato un errore di connessione o usando SessionFactory.getCurrentSession() all'inizio di ogni comunicazione. Ho deciso di utilizzare la seconda opzione (in questo caso la mia applicazione attende il segnale esterno, a volte per ore, quindi sto ottenendo la sessione corrente dopo ogni segnale).


La mia configurazione finale:

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> 

Con questa configurazione c3p0:

  • Ogni 5 minuti di non eseguire qualsiasi query sulla connessione sarà testato, in modo da non sarà mai invalidato dal DB (in configurazione standard, MySQL annulla la connessione dopo 8 ore di inattività),
  • Se DB verrà riavviato o connessione (s) wi Ci saranno due opzioni: a) dopo massimo 5 minuti verranno ripristinate le connessioni, b) se l'applicazione tenta di eseguire una query prima che venga ristabilita la connessione automatica HibernateException, la connessione verrà ristabilita e la successiva query avrà esito positivo.

Opzionalmente testConnectionOnCheckout potrebbe essere impostato su true per evitare eccezioni, ma causerà problemi di prestazioni (vedere documentation).

0

Prova a settare testConnectionOnCheckout su true nel tuo c3p0-config.

0

sei sicuro che c3p0 sia effettivamente inizializzato e che abbia la configurazione che ti aspetti che abbia?

nei registri, a livello di INFO, dovresti vedere un dump della configurazione di DataSource di c3p0 al momento dell'inizializzazione del pool. verifica che sia lì e che sia la configurazione che ti aspetti.

se non è lì, perche non aggiungendo la seguente riga al hibernate.cfg.xml:

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

Hai ragione, c3p0 non è stato inizializzato quando eseguo il mio contenitore di grassi dalla console - vedi la domanda aggiornata. Ho scoperto che nel pacchetto hibernate-c3p0 v4.3.6 non esiste la classe org.hibernate.connection.C3P0ConnectionProvider, ma invece c'è org.hibernate.c3p0.internal.C3P0ConnectionProvider. L'ho usato e sembra buono, c3p0 è inizializzato, sto solo aspettando di verificare se il problema con il controllo delle connessioni è stato risolto. – Radzikowski