web-dev-qa-db-fra.com

Principes de base - Résolution de problèmes de pool de connexions Hibernate/JDBC

Quelle est la responsabilité de Hibernate en ce qui concerne les connexions de base de données provenant d’un pool de connexions sous-jacent? Est-ce qu'il teste pour voir si une connexion est fermée avant de l'utiliser? et si ainsi obtenir une autre connexion de la piscine?

J'ai inclus les informations d'erreur et de confirmation ci-dessous. Toute idée de l'endroit où je pourrais commencer à résoudre ce problème serait très utile. Et tout conseil sur les paramètres du pilote SQL Server que nous utilisons.

du journal Catalina:

 04-Nov-2010 21: 54: 52.691 AVERTISSEMENT org.Apache.Tomcat.jdbc.pool.ConnectionPool.abandon La connexion a été abandonnée par PooledConnection [ID de connexion: 8]: Java.lang.Exception 
. à org.Apache.Tomcat.jdbc.pool.ConnectionPool.getThreadDump (ConnectionPool.Java:926) 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection (ConnectionPool.Java:681) [. .] à org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection (ConnectionPool.Java:545) 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.getConnection (ConnectionPool.Java:6) 
 à org.Apache.Tomcat.jdbc.pool.DataSourceProxy.getConnection (DataSourceProxy.Java:106) 

de notre journal d'application:

 2010-11-04 21: 54: 52,705 [Tomcat-http - 18] WARN util.JDBCExceptionReporter - Erreur SQL: 0, SQLState: 08S01 
 2010-11-04 21:54: 52,707 [Tomcat-http - 18] ERREUR util.JDBCExceptionReporter - Socket fermé 
 2010-11-04 21: 54: 52,708 [Tomcat-http - 18] ERREUR transaction.JDBCTransaction - Echec de la restauration JDBC 
 Java.sql.SQLException: la connexion a déjà été fermée. 
 À org.Apache.Tomcat.jdbc.pool.ProxyConnection.invoke (ProxyConnection.Java:112) 
 À org.Apache. Tomcat.jdbc.pool.JdbcInterceptor.invoke (JdbcInterceptor.Java:94) [.__ org.Apache.Tomcat.jdbc.pool.JdbcInterceptor.invoke (JdbcInterceptor.Java:94) 
 à org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState.invoke (ConnectionState.Java:132) 
 at $ Proxy38.rollback (Source inconnue) 
 at org.hibernate.transaction.JDBCTransa ction.rollbackAndResetAutoCommit (JDBCTransaction.Java:217) 
 à org.hibernate.transaction.JDBCTransaction.rollback (JDBCTransaction.Java:196) 
 à org.springframework.orm.hibernate3.Habernate3.Autorité HibernateTransactionManager.Java:676)
 At org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback (AbstractPlatformTransactionManager.Java:845) 
 Java: 822) 
 À org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing (TransactionAspectSupport.Java:412) 
 À org.springframework.transaction.transaction.interceptor.Transactor.TransactionInterceptor.invocation 111) 
 À org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.Java:172) 
 À org.springframework.aop.f ramework.Cglib2AopProxy $ intercepteur.intercept dynamique (Cglib2AopProxy.Java:625) 

La configuration :

<Resource defaultAutoCommit="false" defaultReadOnly="false"
        defaultTransactionIsolation="SERIALIZABLE"
        driverClassName="com.Microsoft.sqlserver.jdbc.SQLServerDriver"
        factory="org.Apache.Tomcat.jdbc.pool.DataSourceFactory"
        fairQueue="false" initialSize="10"
        jdbcInterceptors="ConnectionState;StatementFinalizer"
        jmxEnabled="true" logAbandoned="true" maxActive="100"
        maxIdle="10" maxWait="30000"
        minEvictableIdleTimeMillis="10000" minIdle="10"
        name="com.ourcompany.ap.shoppingcart/datasource"
        password="somePassword" removeAbandoned="true"
        removeAbandonedTimeout="60" testOnBorrow="true"
        testOnReturn="false" testWhileIdle="false"
        timeBetweenEvictionRunsMillis="5000"
        type="javax.sql.DataSource"
        url="jdbc:sqlserver://approd\approd;databaseName=prod"
        useEquals="false" username="AccessPointNet"
        validationInterval="30000" validationQuery="SELECT 1"/>`
15
BuddyJoe

Quelle est la responsabilité de Hibernate en ce qui concerne les connexions de base de données provenant d’un pool de connexions sous-jacent?.

Pas grand chose, le relâcher quand la Session est fermée.

Est-ce qu'il teste pour voir si une connexion est fermée avant de l'utiliser? et si ainsi obtenir une autre connexion de la piscine?

Non, pas Hibernate, la vérification de la validité de connexion (s) est la responsabilité d'un pool de connexion si vous le souhaitez.

J'ai inclus les informations d'erreur et de confirmation ci-dessous. Toute idée de l'endroit où je pourrais commencer à résoudre ce problème serait très utile.

Quel genre de processus exécutez-vous exactement? Une longue transaction? Est-ce qu'il expire? Que dit leCaused by:? A propos de la trace:

 2010-11-04 21: 54: 52,705 [Tomcat-http - 18] WARN util.JDBCExceptionReporter - Erreur SQL: 0, SQLState: 08S01 
 2010-11-04 21:54: 52 707 [Tomcat-http - 18] ERREUR util.JDBCExceptionReporter - Socket fermé 
 2010-11-04 21: 54: 52,708 [Tomcat-http - 18] ERREUR transaction.JDBCTransaction - L'annulation JDBC a échoué Java.sql .SQLException: la connexion a déjà été fermée. 

Pouvez-vous le reproduire de manière déterministe? Un problème de réseau?

Et tout conseil sur les paramètres du pilote SQL Server que nous utilisons.

J'ai ajouté une excellente ressource sur Tomcat et la configuration du pool de connexions ci-dessous. Pas spécifique à SQL Server cependant.

Ressources

14
Pascal Thivent

J'ai eu un problème similaire qui a été résolu en augmentant la valeur removeAbandonedTimeout à un nombre plus élevé. Le problème que nous avons rencontré était dû à la requête qui a pris plus de temps que le délai mentionné ci-dessus.

17
Cid

Nous travaillons généralement autour de cela en utilisant dbcp et en fournissant une requête de validation lors de la définition de notre source de données. Ensuite, dbcp vérifiera l'utilisabilité des connexions en pool en émettant cette requête (et recréera de manière transparente la connexion si elle ne fonctionne plus), avant de les renvoyer à l'application.

Consultez http://Tomcat.Apache.org/Tomcat-6.0-doc/jndi-datasource-examples-howto.html pour plus de détails.

2
meriton

J'utilise actuellement liquibase(v1.9) dans mon projet et lorsque les changesSets sont exécutés sur un schéma vide, cela prend toujours plus de 60 secondes, ce qui entraîne le marquage du thread comme étant abandonné. Je ne suis pas ravi d'augmenter la valeur removeAbandonedTimeoutname__, mais c'est la seule solution. J'ai pu trouver pour empêcher ce problème; cependant, une fois la population de schéma initiale terminée, le problème est rarement rencontré. Je redéfinis la valeur sur 60 secondes.

2
mjj1409

J'ai travaillé sur un problème dans le passé où nous ne retournions pas correctement les connexions à la piscine. Ainsi, lorsqu'une connexion était utilisée et non renvoyée, le fait d'appeler une base de données en temps voulu entraînerait une exception.

Nous avons réussi à reproduire le problème en appelant la base de données, avons attendu 8 heures (délai d'attente par défaut de Postgres) et avons tenté à nouveau d'appeler la base de données. Il jette la même exception à chaque fois. Notre solution consistait à repenser (ou mieux encore, ajouter ) une stratégie de gestion des connexions.

Donc, pour résumer, retournez-vous réellement vos connexions au pool en fermant la session?

1
Jeremy

J'ai eu la solution pour l'exception ci-dessus. Fermez simplement l'instance de la fabrique de sessions lors de la fermeture de la session.

Regardez le code ci-dessous:

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        }
        catch (Throwable ex) {
            ex.printStackTrace();
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionfactory() {
        return sessionFactory;
    }

    public static Session getSession() {
        Session session=sessionFactory.openSession();
        session.getTransaction().begin();
        return session;
    }
    public static void closeSession(Session session) {
        if(session!=null )
        {
            if(session.getTransaction().isActive())
            {
                session.getTransaction().commit();
            }
                session.close();
                getSessionfactory().close();
        }
    }
}

il suffit d'appeler la méthode HibernateUtil.closeSession () . Cela résoudra le problème.

0
user3247321