web-dev-qa-db-fra.com

Aucune opération autorisée après la fermeture de la connexion

Je reçois cette erreur d'une application Java:

com.mchange.v2.c3p0.impl.NewPooledConnection - [c3p0] Another 
error has occurred [     
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 
No operations allowed after connection closed. ] which will not be 
reported to listeners!

Le code Java:

try {
    sessionFactory.beginTransaction();
    //...
    sessionFactory.commitTransaction();
} catch (Exception e) {
    sessionFactory.rollbackTransaction();
    throw new RuntimeException(e);
}

L'usine de session:

try {
    sessionFactory.beginTransaction();
    ...
    sessionFactory.commitTransaction();
} catch (Exception e) {
    sessionFactory.rollbackTransaction();
    throw new RuntimeException(e);
}

public Transaction beginTransaction() throws HibernateException {
    try {
        return sessionFactory.getCurrentSession().beginTransaction();
    } catch (HibernateException hex) {
        LOG.error(String.format("Unable to start database transaction due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
    }
}

public void commitTransaction() throws HibernateException {
    LOG.debug("Committing database transaction.");
    try {
        if (sessionFactory.getCurrentSession().getTransaction().isActive()) {
            sessionFactory.getCurrentSession().getTransaction().commit();
        } else {
            throw new HibernateException("Transaction is no longer Active.");
        }
    } catch (HibernateException hex) {
        LOG.error(String.format("Unable to commit due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
    }
}

public void rollbackTransaction() throws HibernateException {
    LOG.debug("Trying to rollback database transaction after exception.");
    Session session = sessionFactory.getCurrentSession();
    try {
        if (session.getTransaction().isActive()) {
            session.getTransaction().rollback();
        } else {
            throw new HibernateException("Transaction is no longer Active.");
        }
    } catch (HibernateException hex) {
        LOG.error(String.format("Unable to rollback due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
    } finally {
        if (session.isOpen()) {
            session.close();
        }
    }
}

Paramètres Hibernate et C3P0:

<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.c3p0.timeout">1800 <!-- seconds --></prop>
<prop key="hibernate.c3p0.min_size">4</prop>
<prop key="hibernate.c3p0.max_size">35</prop>
<prop key="hibernate.c3p0.idle_test_period">240 <!-- seconds --></prop>
<prop key="hibernate.c3p0.acquire_increment">4</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.preferredTestQuery">SELECT 1</prop>
<prop key="c3p0.testConnectionOnCheckout">true</prop>
<prop key="hibernate.connection.Oracle.jdbc.ReadTimeout">60000 <!-- milliseconds --></prop>

Vous ne savez pas comment la connexion peut encore être utilisée et cette erreur est générée. Qu'est ce qui cause cette erreur?

7
tuxx

Cette méthode Java appelée executeQuery:

your_database_connection.createStatement().executeQuery(your_string_query);

jettera cette exception:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 
No operations allowed after connection closed.

si vous essayez de l'exécuter (executeQuery) après avoir appelé:

your_database_connection.close()

Qu'est-ce qui se passe

Soit vous essayez d’obtenir une connexion à la base de données mais vous n’en obtenez pas et vous essayez d’exécuter une requête qui échoue. Ou vous avez eu une connexion qui a eu un problème et est devenue fermée et vous avez essayé d'exécuter une autre requête à travers elle.

La solution  

En supposant que vous ayez perdu la connexion en raison de problèmes de réseau ou de quelque chose qui ne soit pas de votre faute, placez le code qui tente la requête dans un bloc try/catch. En cas d'erreur, attendez 10 secondes et reconnectez-vous à la base de données.

3
Eric Leschinski

votre idleConnectionTestPeriod est 240, il devrait être inférieur à la valeur du délai d'attente de la base de données, voir la configuration de la base de données, vérifiez que la valeur est supérieure à 240.

0
jerry_li