How to avoid stale MySQL/Hibernate connections (MySQLNonTransientConnectionException) - java

I have a Java webapp using Hibernate and MySQL. If the site isn't used for a few days, the MySQL connection goes stale, and I am met with the following exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
From experience using raw JDBC it is possible to configure the connection to attempt to recover from errors or stale connections, but I don't know how to do this using Hibernate. I am not explicitly calling close() anywhere (but I am betting Hibernate does somewhere deep down in its guts).
Does anybody know what I should do?

What connection pool are you using?
The Hibernate suggestion is not to use the built-in pooling, but use the application server datasource or something like Commons DBCP or C3PO.

I had that problem. Using connection pooling (c3p0) made it go away. It is also a good idea in general to use some connection pooling.

Thanks for the advice. For posterity's sake, I changed the hibernate.cfg.xml from the following:
<property name="connection.url">jdbc:mysql://localhost/FooDB</property>
<property name="connection.username">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">secret</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
... to the following:
<property name="connection.datasource">java:/comp/env/jdbc/FooDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
This also required adding a standard 'context' entry in my web app's context.xml:
<Resource name="jdbc/FooDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="secret"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/ss?autoReconnect=true" />

We had a similar problem of hibernate mysql connection getting timed out.
So we tried C3P0, with the following configuration:
<property name=c3p0.acquire_increment>1</property>
<property name=c3p0.idle_test_period>3600</property>
<property name=c3p0.max_statements>0</property>
<property name=c3p0.min_size>1</property>
<property name=c3p0.timeout>3605</property>
<property name=hibernate.c3p0.preferredTestQuery>select 1;</property>
Hibernate connection_pool size was set to 1.
This made the timeout problem go away. But we started facing another problem. Long waits.
We have a service (servlet running on jboss), which receives something like 5-6 requests per second. Every request needs to connect to mysql through hibernate. Most of our requests do selects, with an insert/update every 5th-6th request. Normally the request serve time for us is 2-3ms for select and 40-50ms for insert/update. But, after using the above C3P0 configuration, we saw that every request completing after an update was taking almost 4-5 minutes! From our logs, it seemed that randomly a select request will get stuck and will be able to complete only after an update request was received and served.
Above problem goes away if we remove the C3P0 config. Can somebody suggest what we could be doing wrong?
Here is the complete hibernate config for reference:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://xxx.xxx.xxx</property>
<property name="connection.username">xxx</property>
<property name="connection.password">xxx</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="show_sql">true</property>
<!-- Transaction isolation 2 = READ_COMMITTED -->
<property name="connection.isolation">2</property>
<property name="connection.autocommit">true</property>
<!-- configuration pool via c3p0-->
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">3600</property> <!-- seconds -->
<property name="c3p0.max_size">1</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.timeout">3605</property> <!-- seconds -->
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
</session-factory>
</hibernate-configuration>

<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">120</property> <!-- seconds -->
<property name="c3p0.max_size">100</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">10</property>
<property name="c3p0.timeout">180</property> <!-- seconds -->
override these settings on your config file. It ll helps to you.

Related

Second level caching in hibernate while migrating from JBoss to TomEE

I need to migrate my application built in GWT from Jboss to tomEE. The application has second level caching enabled in hibernate using Jboss cache. Is it possible to use Jboss cache in tomEE or do I have to find an alternative? If possible, can anyone please help me with the configuration of hibernate.cfg.xml? Below is the configuration
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.sybase.jdbc3.jdc.Sybdriver</property>
<property name="hibernate.connection.url">xyz...</property>
<property name="hibernate.connection.username">xyz..</property>
<property name="hibernate.connection.password">xyz..</property>
<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
<property name="dialect">org.hibernate.dialect.SybaseASE15Dialect</property>
<property name="generate_statistics">false</property>
<property name="jdbc.use_scrollable_resultset">false</property>
<property name="cache.provider_class">org.hibernate.cache.jbc.JBossCacheRegionFactory</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_minimal_puts">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory</property>
<property name="cache.region.jbc2.cachefactory">java:CacheManager</property>
<property name="cache.region.jbc2.cfg.entity">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.collection">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.query">local-query</property>
<mapping resource="book.hbm.xml" />
</session-factory>
</hibernate-configuration>
We cannot achieve the second level caching using JBoss cache in TomEE. We have implemented a similar caching mechanism using Ehcache which is a little slow but works fine.
<property name="cache.region.jbc2.cfg.entity">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.collection">mvcc-entity</property>
<property name="cache.region.jbc2.cfg.query">local-query</property>
We see that entity, collection, and query caching are enabled by using JBoss cache implementation specific to JBoss server. In the case of TomEE, we cannot have the same configuration. You would have to implement a different caching technique using different caching technologies available and match it with the usage of second-level cache(like say read-only, read-write, transactional etc.). In a similar setup, I had used "Ehcache" and that had solved the problem.

ArrayIndexOutOfBounds - Hibernate

I am using hibernate with a database wich is in a WAS (Websphere Application Server [IBM]) and I am getting this error sometimes:
java.lang.ArrayIndexOutOfBoundsException
at com.ibm.ws.rsadapter.spi.CacheMap.removeLRU(CacheMap.java:378)
at com.ibm.ws.rsadapter.spi.CacheMap.add(CacheMap.java:180)
at com.ibm.ws.rsadapter.spi.WSRdbManagedConnectionImpl.cacheStatement(WSRdbManagedConnectionImpl.java:3150)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.closeWrapper(WSJdbcPreparedStatement.java:513)
at com.ibm.ws.rsadapter.jdbc.WSJccPreparedStatement.closeWrapper(WSJccPreparedStatement.java:290)
at com.ibm.ws.rsadapter.jdbc.WSJdbcObject.close(WSJdbcObject.java:241)
at com.ibm.ws.rsadapter.jdbc.WSJdbcObject.close(WSJdbcObject.java:194)
at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:563)
at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:291)
at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:214)
at org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1300)
at org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:365)
Is a multithread application, so may be some stuff related with the cache of hibernate when multiple access are performed, but I am not sure about it. The error is thrown when the hibernate query sentence is executed like
query.list();
or
query.executeUpdate();
I have tried to set the cacheable to false and the CacheMode to IGNORE:
Session session = getSession();
session.setCacheMode(CacheMode.IGNORE);
session.createSQLQuery('query').setCacheable(false);
for disabling the cache, but the exceptions keep appearing, as I said, sometimes.
My hibernate-config.xml is this one:
<hibernate-configuration>
<session-factory name="HibernateSessionFactory">
<property name="hibernate.dialect">${hibernate.dialect}</property>
<property name="hibernate.show_sql">${hibernate.show_sql}</property>
<property name="hibernate.format_sql">${hibernate.format_sql}</property>
<property name="hibernate.use_sql_comments">${hibernate.use_sql_comments}</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="hibernate.connection.aggressive_release">false</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.connection.pool_size">0</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.transaction.auto_close_session">true</property>
<property name="hibernate.transaction.flush_before_completion">true</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
</session-factory>
</hibernate-configuration>
Here you can see as I keep trying to totally disable the cache, but It still not work properly.
Any help or suggestion would be appreciated.
Thank you very much in advance! :D

Hibernate c3p0 configuration has no affect

I'm trying to add c3p0 connection pool to our existing hibernate configuration.
But it has no affect and hibernate still uses default pool.
Hibernate Configuration alone is working fine so i am absolutely sure no problem with it.
Wondering if someone here can point my mistake Or suggest how i can debug the problem ?
I do not use Spring framework.
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
<property name="hibernate.connection.password">passwd</property>
<property name="hibernate.connection.url">jdbc:db2://server:port/database</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.default_schema">DB Schema</property>
<property name="hibernate.dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="hibernate.format_sql">false</property>
<property name="hibernate.max_fetch_depth">4</property>
<property name="hibernate.search.autoregister_listeners">false</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.connection.isolation">1</property>
<property name="hibernate.jdbc.batch_size">50</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">3000</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">900</property>
<mapping resource="table.hbm.xml" />
</session-factory>
</hibernate-configuration>
Here are the jars i have:
hibernate3.jar
hibernate-c3p0-3.5.0-Final.jar
Statements from the logs:
hibernate.cfg.Environment - Hibernate 3.5.0-Final
INFO ManagerConnectionProvider - Using Hibernate built-in connection pool (not for production use!)
INFO ManagerConnectionProvider - Hibernate connection pool size: 20
Try configuring a connection provider class from c3p0.
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
Also, it's better to add the hibernate configuration doctype, which will help in finding any typos.
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
UPDATE
You need to include the mchange library in your classpath. This link might helpful to you.

Hibernate 4, EnversIntegrator could not be instantiated

I'm trying to set up Hibernate, and since 4.0.0 just came out I naturally decided to go with that. It seems that no matter what way I try to create a SessionFactory, it always leads to the same error:
Initial SessionFactory creation failed.java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.hibernate.envers.event.EnversIntegrator could not be instantiated: java.lang.ClassCastException: Cannot cast org.hibernate.envers.event.EnversIntegrator to org.hibernate.integrator.spi.Integrator
It seems like there is something wrong with my Hibernate configuration but I can't figure out what. Here's my 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>
<!-- Database connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://192.168.0.17:5432/mydb</property>
<property name="connection.username">myusrname</property>
<property name="connection.password">mypasswd</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- c3p0 configuration -->
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">false</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
</session-factory>
</hibernate-configuration>
Does anyone spot anything out of the ordinary, or do you have other ideas?
I found no way to get Hibernate 4.0.0 CR4 working. Switching to 3.6.7 resolved the problem and works just fine. I conclude that there must be some bug in the release, and will file a bug report.

Hibernate and too many connections

I am working on web-project with Hibernate ans Spring MVC.
My hibernate configuration is:
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/xxx</property>
<property name="connection.username">xxx</property>
<property name="connection.password">xxx</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>\<property name="hibernate.c3p0.max_statements">50</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="connection.useUnicode">true</property>
<property name="connection.characterEncoding">UTF-8</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
The hibernate sessions are closing in service-classes destructors (these service-classes have DAO objects). But after publishing at production server I've got too many connections exception from mysql.Every server call, the mysql connection was opened. When the connections amount become 101 - db failed. I think that destructors had not time enought for executes so the connections were opened all the time.
Then, I rebuilded the structure. Now, the Spring controllers call the service-class function, that releases the session mannualy. But it doesn't help: the connections are still opened and now I can not use LAZY-collections in views because the session already closed.
How can I solve that problem? What is the usual approach here?
Thank you.

Categories

Resources