Hallo Forum,
mal eine Frage zu Hibernate/MySQL:
Ist es normal, dass die Pooling-Connections die sich Hibernate bei mir mit c3p0 für MySQL holt, nach dem Ende der Anwendung nicht geschlossen werden? (Sichtbar im Mysql-Admin unter "Aktive Verbindungen"). Bei jedem neuen Start der App werden nämlich wieder neue Connections gepoolt, bei meiner Einstellung von mindestens 15 Connections hab ich nach 3 Starts 45 Verbindungen offen (und so weiter, biss der DB-Server sie anhand des Timeouts schliesst, was ewig dauern kann. Und die Einstellung des DB-Timeouts liegt nicht in meiner Macht).
Wenn das nicht normal ist, wie kann ich ich das Schliessen der Verbindungen beim Beenden der Anwendung forcieren?
Meine Hibernate-Config sieht folgendermaßen aus:
Zum statischen Zugriff auf Session und Transaktionen verwende ich das ThreadLocal-Pattern.
mal eine Frage zu Hibernate/MySQL:
Ist es normal, dass die Pooling-Connections die sich Hibernate bei mir mit c3p0 für MySQL holt, nach dem Ende der Anwendung nicht geschlossen werden? (Sichtbar im Mysql-Admin unter "Aktive Verbindungen"). Bei jedem neuen Start der App werden nämlich wieder neue Connections gepoolt, bei meiner Einstellung von mindestens 15 Connections hab ich nach 3 Starts 45 Verbindungen offen (und so weiter, biss der DB-Server sie anhand des Timeouts schliesst, was ewig dauern kann. Und die Einstellung des DB-Timeouts liegt nicht in meiner Macht).
Wenn das nicht normal ist, wie kann ich ich das Schliessen der Verbindungen beim Beenden der Anwendung forcieren?
Meine Hibernate-Config sieht folgendermaßen aus:
Code:
<?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.url">
jdbc:mysql://server:3306/db
</property>
<property name="connection.username">user</property>
<property name="connection.password">password</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="dialect">
org.hibernate.dialect.MySQL5InnoDBDialect
</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="current_session_context_class">
thread
</property>
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
<property name="hibernate.connection.useUnicode">
true
</property>
<property name="hibernate.connection.charSet">
UTF-8
</property>
<property name="hibernate.connection.characterEncoding">
UTF-8
</property>
<property name="hibernate.hbm2ddl.auto">
update
</property>
<property name="hibernate.c3p0.acquire_increment">
1
</property>
<property name="hibernate.c3p0.idle_test_period">
100
</property>
<property name="hibernate.c3p0.initialPoolSize">
10
</property>
<property name="hibernate.c3p0.min_size">
15
</property>
<property name="hibernate.c3p0.max_size">
50
</property>
<property name="hibernate.c3p0.timeout">
1800
</property>
<mapping class="........." />
</session-factory>
</hibernate-configuration>
Zum statischen Zugriff auf Session und Transaktionen verwende ich das ThreadLocal-Pattern.
Code:
package ie.gov.agriculture.dpcs.hibernate;
import java.io.FileInputStream;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.exception.ConstraintViolationException;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
private static Log log = LogFactory.getLog(HibernateUtil.class);
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
log.debug("Created Hibernate Session Factory");
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
log.debug("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
*
* @return
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* Create a new Session if no session exists
* and add it to the current thread.
*
* @return the current session
*/
public static Session getSession() {
Session s = (Session)threadSession.get();
// Open a new Session, it this thread has none yet
try {
if(s== null) {
log.debug("SessionFactory is closed = " + sessionFactory.isClosed());
s = sessionFactory.openSession();
log.debug("Session is connected = " + s.isConnected()+ " And is open = " + s.isOpen());
log.debug("HibernateUtil::Opening new Hibernate Session");
threadSession.set(s);
log.debug("HibernateUtil::Added Session to current Thread");
}
} catch (HibernateException e) {
log.debug("HibernateException Getting Session::" + e.getMessage());
e.printStackTrace();
}
return s;
}
/**
* Remove the session from the current thread
* and if it is open, close it.
*
*/
public static void closeSession() {
try {
Session s = (Session)threadSession.get();
threadSession.set(null);
log.debug("HibernateUtil::Closing Hibernate Session");
if( s != null && s.isOpen()) {
s.close();
}
} catch (HibernateException e) {
log.debug("HibernateException Closing Session::" + e.getMessage());
e.printStackTrace();
}
}
/**
* If no transaction exists, create a new one and add it to
* this thread
*
*/
public static void beginTransaction() {
Transaction tx = (Transaction)threadTransaction.get();
try{
if(tx == null) {
log.debug("HibernateUtil::Starting new Hibernate Transaction");
tx = getSession().beginTransaction();
threadTransaction.set(tx);
log.debug("HibernateUtil::Added Hibernate Transaction to local thread:: tx is Active= " + tx.isActive());
}
} catch (HibernateException e) {
log.debug("HibernateException Beginning Transaction::" + e.getMessage());
e.printStackTrace();
}
}
/**
* Commit the Transaction if it has not been comitted or
* rolled back already.
*
*/
public static void commitTransaction() {
Transaction tx = (Transaction)threadTransaction.get();
try {
threadTransaction.set(null);
if(tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack()) {
log.debug("HibernateUtil::Commiting Hibernate Transaction");
tx.commit();
}
} catch (ConstraintViolationException e) {
log.debug("HibernateException Rolling Back Transaction::" + e.getMessage());
rollbackTransaction();
throw e;
} catch (HibernateException e) {
log.debug("HibernateException Rolling Back Transaction::" + e.getMessage());
rollbackTransaction();
e.printStackTrace();
}
}
public static void attemptCommitTransaction() {
Transaction tx = (Transaction)threadTransaction.get();
threadTransaction.set(null);
if(tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack()) {
log.debug("HibernateUtil::Attempting to Commit Hibernate Transaction");
tx.commit();
}
}
/**
* Roll back transaction if it has not been comitted
* or rolled back already
*
*/
public static void rollbackTransaction() {
Transaction tx = (Transaction)threadTransaction.get();
log.debug("HibernateUtil::About to Rollback Hibernate Transaction:: tx is Active= " + tx.isActive());
try {
threadTransaction.set(null);
if(tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack()) {
log.debug("HibernateUtil::Rollingback Hibernate Transaction");
tx.rollback();
}
} catch (HibernateException e) {
log.debug("HibernateException Rolling Back Transaction::" + e.getMessage());
e.printStackTrace();
} finally {
closeSession();
}
}
}