2014-10-27 2 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 (исполняющему по Maven из 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

При выполнении jar, созданного maven-shade-plugin, я получаю:

Paz 27, 2014 10:56:22 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator instantiateC3p0Provider WARN: HHH000022: C3P0 свойства встречаются, но класс поставщик c3p0 не был найден classpath; эти свойства будут игнорироваться. Paz 27, 2014 10:56:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl настроить WARN: HHH000402: Использование Hibernate встроенный в пул соединений (! не для использования в производстве) Paz 27, 2014 10:56:22 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator

или когда я попытался указать org.hibernate.connection.C3P0ConnectionProvider в свойствах:

INFO: HHH000130: Инстанцирование явный соединение p rovider: org.hibernate.connection.C3P0ConnectionProvider Начальная SessionFactory создание failed.org.hibernate.service.spi.ServiceException: Невозможно составить запрошенную услугу [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] Exception in thread "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

Хорошо, я сумел решить все проблемы. Вот душа.

Прежде всего, как предположил Стив Вальдман, c3p0 не был инициализирован, но в Hibernate 4.3 hibernate.connection.provider_class параметр должен быть: org.hibernate.c3p0.internal.C3P0ConnectionProvider. В documentation вы можете прочитать:

Поставщик соединения, использующий пул соединений C3P0. Hibernate будет использовать это по умолчанию, если установлены свойства 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 минут не выполняет никаких запросов на связи будут опробованы, так что никогда не будет аннулирован БД (в стандартной конфигурации MySQL аннулирует соединение после 8 часов бездействия),
  • Если БД будет перезапущен или подключен wi Если у вас есть два варианта: a) после 5 минут соединения будут восстановлены, b) если приложение пытается выполнить запрос перед автоматическим восстановлением соединения HibernateException, то соединение будет восстановлено, и следующий запрос будет успешным.

Опционально testConnectionOnCheckout может быть установлен верно для предотвращения исключения, но это вызовет проблемы производительности (см documentation).

0

Попробуйте установить testConnectionOnCheckout в true в c3p0-config.

0

Вы уверены, что c3p0 фактически инициализирован и что у него есть конфигурация, которую вы ожидаете от него?

в ваших журналах, на уровне INFO вы должны увидеть дамп конфигурации вашего c3p0 DataSource при инициализации пула. убедитесь, что он есть, и что это ожидаемая конфигурация.

, если нет, пожалуйста, рассмотреть вопрос о включении в следующую строку в hibernate.cfg.xml:

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

Вы правы, c3p0 не был инициализирован, когда я выполняю свою толстую банку с консоли - см. Обновленный вопрос. Я узнал, что в пакете hibernate-c3p0 v4.3.6 нет класса org.hibernate.connection.C3P0ConnectionProvider, но вместо этого существует org.hibernate.c3p0.internal.C3P0ConnectionProvider. Я использовал его, и он выглядит хорошо, c3p0 инициализирован, я только жду, чтобы проверить, разрешена ли проблема с проверкой соединений. – Radzikowski

Смежные вопросы