C3P0 não reutiliza conexões do pool

Boa noite caros colegas!

Estou tendo algum vazamento de conexões no meu aplicativo.
Eu uso hibernate com c3p0 e tenho uma factory:

public class ConnectionFactory {
private static EntityManagerFactory entityManagerFactory;

public static EntityManagerFactory getEntityManagerFactory() {
    if (entityManagerFactory != null) {
        return entityManagerFactory;
    } else {
        return entityManagerFactory = Persistence.createEntityManagerFactory("helitelaudos");
    }
}

}

Abaixo, alguns métodos DAO que utilizo, verifique que todos tem o fechamento em.close():

public boolean apagar(Laudo laudo) throws Exception {
    EntityManager em = ConnectionFactory.getEntityManagerFactory().createEntityManager();

    try {
        em.getTransaction().begin();
        em.remove(em.getReference(Laudo.class, laudo.getId()));
        em.getTransaction().commit();
        return true;
    } catch (Exception e) {
        em.getTransaction().rollback();
        throw new Exception("Houve um problema ao deletar o laudo no servidor FTP.\n" + e.getMessage());
    } finally {
        em.close();
    }
}

public List<Laudo> listarTodosTableModel() throws Exception {
    List<Laudo> laudos = new ArrayList<Laudo>();

    EntityManager em = ConnectionFactory.getEntityManagerFactory().createEntityManager();

    try {
        em.getTransaction().begin();
        laudos = em.createQuery(
                "select l from Laudo l " +
                        "order by l.id desc ",
                Laudo.class
        ).setMaxResults(100).getResultList();
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    } finally {
        em.close();
    }

    return laudos;
}

Desconfio que algo nesse “Singleton” esteja errado.
Ao monitorar o banco, as conexões abertas ficam em sleep não sendo reutilizadas pelo c3p0.

Para a aplicação rodar, defini um número alto de conexões permitidas. Abaixo minha configuração:

<!-- Configurações do Hibernate -->
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL57Dialect"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <!-- Atualiza o banco de dados, criando as tabelas caso necessário -->
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <property name="hibernate.useSSL" value="false"/>
        <property name="hibernate.use_sql_comments" value="true"/>
        <property name="hibernate.generate_statistics" value="false"/>
        <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>

        <!-- Configurações C3PO -->

        <property name="hibernate.c3p0.min_size" value="5"/>
        <property name="hibernate.c3p0.max_size" value="100"/>
        <property name="hibernate.c3p0.timeout" value="1800"/>
        <property name="hibernate.c3p0.acquire_increment" value="5"/>
        <property name="hibernate.c3p0.max_statements" value="50"/>
        <property name="hibernate.c3p0.idle_test_period" value="3000"/>
        <!--<property name="hibernate.c3p0.statementCacheNumDeferredCloseThreads" value="1"/>-->
        <!--<property name="hibernate.c3p0.numHelperThreads" value="10"/>-->
        <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces" value="true"/>
        <property name="hibernate.c3p0.unreturnedConnectionTimeout" value="1850"/>

Abaixo log de inicialização do c3p0:

INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
fev. 08, 2021 12:29:48 AM org.hibernate.c3p0.internal.C3P0ConnectionProvider configure
INFO: HHH010002: C3P0 using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://host/banco?createDatabaseIfNotExist=true&useSSL=false
fev. 08, 2021 12:29:48 AM org.hibernate.c3p0.internal.C3P0ConnectionProvider configure
INFO: HHH10001001: Connection properties: {password=****, user=user}
fev. 08, 2021 12:29:48 AM org.hibernate.c3p0.internal.C3P0ConnectionProvider configure
INFO: HHH10001003: Autocommit mode: false
[MLog-Init-Reporter] INFO com.mchange.v2.log.MLog - MLog clients using slf4j logging.
[Thread-0] INFO com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
fev. 08, 2021 12:29:48 AM org.hibernate.c3p0.internal.C3P0ConnectionProvider configure
INFO: HHH10001007: JDBC isolation level: <unknown>
[Thread-0] INFO com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@a4313d72 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@303e736e [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, identityToken -> 2rvxwoafzffwowdihgf1|5e19ced2, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 100, maxStatements -> 50, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@6390cdf1 [ description -> null, driverClass -> null, factoryClassLocation -> null, forceUseNamedDriverClass -> false, identityToken -> 2rvxwoafzffwowdihgf1|1b6db83c, jdbcUrl -> jdbc:mysql://host/banco?createDatabaseIfNotExist=true&useSSL=false, properties -> {password=******, user=******} ], preferredTestQuery -> null, privilegeSpawnedThreads -> false, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 1850, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, extensions -> {}, factoryClassLocation -> null, identityToken -> 2rvxwoafzffwowdihgf1|c6f48dc, numHelperThreads -> 3 ]
fev. 08, 2021 12:29:51 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@408ca35f] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
fev. 08, 2021 12:30:04 AM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]

Poderiam me dar uma luz nesse caso? Desde já sou grato a todos!

Alguém?

Outro ponto é que parece não fechar quando não tem commit no DAO, no caso, os Selects.
Vêem algum problema nesse factory ou no fato de eu sempre instanciar em todos os métodos?
Já pensei de tudo que é jeito…

@staroski @ViniGodoy

Estou em desespero :astonished:

Upando

É esse o propósito de usar uma pool de connections. Quando fechas a conexão no teu código na realidade estás apenas a retornar para a pool e a pool é que decide quando fecha conexões ou abre mais, consoante a utilização que está a ser necessária e as configurações.
Talvez se baixares o valor de hibernate.c3p0.max_size consigas ver facilmente conexões a serem reutilizadas.

1 curtida

Boa tarde!

Tinha setado max em 15. Porém ele vai criando as conexões e quando chega em 15 a thread trava, esperando até outra conexão liberar. (Liberava antes pelo hibernate.c3p0.unreturnedConnectionTimeout, setado com 10 minutos)

Vê algum problema em meu código? Algo que eu possa fazer?

Depois de um fim de semana de testes, encontrei o erro.
Onde eu fazia select nos DAOs eu estava iniciando uma transação em.getTransaction().begin().
Ao ler a documentação, fui informado que não precisamos abrir uma transação para fazer selects.
A correção foi remover este trecho que inicia a transação em todos os selects.

Obrigado @pmlm por tentar ajudar a solucionar o problema!