最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - EntityManager.close not releasing connection back to the pool - Stack Overflow

programmeradmin0浏览0评论

I have an old spring application that uses the following configuration for Spring JPA and Hibernate:

<bean id="myEmf" class=".springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>

        <property name="jpaVendorAdapter">
            <bean class=".springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value=".hibernate.dialect.MySQLDialect"/>
            </bean>
        </property>        
        <property name="persistenceUnitName" value="LPU"/>
        <property name="persistenceUnitManager">
            <bean class=".springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
                <property name="defaultDataSource" ref="dataSource"></property>
            </bean>
        </property>
        <property name="loadTimeWeaver">
            <bean class=".springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
    </bean>

The DAO code correctly gets injected with the above EMF and it uses a ThreadLocal to get/create an EntityManager. After using the EM, it calls em.close(). However, even after calling em.close() the hikaricp connection pool stats show that the connection is not released back to the pool. This is causing cp to run out of connection.

Any idea what might be wrong in this config?

=======ADDED LATER ====== I removed HibernateJpaVendorAdapter and added the following to persistence.xml, yet no difference:

<persistence-unit name="LPU" transaction-type="RESOURCE_LOCAL">
<provider>.hibernate.jpa.HibernatePersistenceProvider</provider>    
    <properties>
    <property name="hibernate.connection.release_mode" value="after_transaction" />
    <property name="hibernate.current_session_context_class" value="jta" />        
     </properties>
</persistence-unit>

I have made sure that entityManager.close() is invoked at the end of the request using a filter. There is no other entitymanager instance open.

public void closeEntityManager(){
    EntityManager em = (EntityManager) threadLocal.get();
    if (em != null && em.isOpen()) {
        if(em.isJoinedToTransaction()){
            em.getTransaction()mit();
        }
        em.flush();
        em.clear();
        em.close();
        //((.hibernate.Session) em.getDelegate()).close();
        threadLocal.remove();
  }
}

I have also tried changing the connection pool imp from HikariCP to Apache commons dbcp.

But the result is the same. Hibernate is not releasing database connection back to the pool.

I have an old spring application that uses the following configuration for Spring JPA and Hibernate:

<bean id="myEmf" class=".springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>

        <property name="jpaVendorAdapter">
            <bean class=".springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value=".hibernate.dialect.MySQLDialect"/>
            </bean>
        </property>        
        <property name="persistenceUnitName" value="LPU"/>
        <property name="persistenceUnitManager">
            <bean class=".springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
                <property name="defaultDataSource" ref="dataSource"></property>
            </bean>
        </property>
        <property name="loadTimeWeaver">
            <bean class=".springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
    </bean>

The DAO code correctly gets injected with the above EMF and it uses a ThreadLocal to get/create an EntityManager. After using the EM, it calls em.close(). However, even after calling em.close() the hikaricp connection pool stats show that the connection is not released back to the pool. This is causing cp to run out of connection.

Any idea what might be wrong in this config?

=======ADDED LATER ====== I removed HibernateJpaVendorAdapter and added the following to persistence.xml, yet no difference:

<persistence-unit name="LPU" transaction-type="RESOURCE_LOCAL">
<provider>.hibernate.jpa.HibernatePersistenceProvider</provider>    
    <properties>
    <property name="hibernate.connection.release_mode" value="after_transaction" />
    <property name="hibernate.current_session_context_class" value="jta" />        
     </properties>
</persistence-unit>

I have made sure that entityManager.close() is invoked at the end of the request using a filter. There is no other entitymanager instance open.

public void closeEntityManager(){
    EntityManager em = (EntityManager) threadLocal.get();
    if (em != null && em.isOpen()) {
        if(em.isJoinedToTransaction()){
            em.getTransaction()mit();
        }
        em.flush();
        em.clear();
        em.close();
        //((.hibernate.Session) em.getDelegate()).close();
        threadLocal.remove();
  }
}

I have also tried changing the connection pool imp from HikariCP to Apache commons dbcp.

But the result is the same. Hibernate is not releasing database connection back to the pool.

Share Improve this question edited Nov 20, 2024 at 6:46 Priyshrm asked Nov 19, 2024 at 13:29 PriyshrmPriyshrm 1,1701 gold badge13 silver badges24 bronze badges 3
  • Changing release_mode to after_statement seems to be working but I am not sure what is the impact of releasing the connection to the pool after each statement because servicing queries from different requests using the same connection may cause issues with the transaction, right? – Priyshrm Commented Nov 20, 2024 at 6:50
  • You should not be able to call em.flush without an active transactional context - this should be giving you an error. Something more is going on. – Chris Commented Nov 20, 2024 at 19:03
  • Good point. I put debug statements before and after flush and have verified it is causing not throwing any exception even when txn has been committed. I also put System.out.println(em.isJoinedToTransaction()); right afterI create an EM, and it prints false (that means autocommit is indeed false). – Priyshrm Commented Nov 21, 2024 at 4:31
Add a comment  | 

1 Answer 1

Reset to default 0

Found the issue. Changed em.isJoinedToTransaction() to em.getTransaction().isActive() and now it is working fine.

if(em.getTransaction().isActive()){
            em.getTransaction()mit();
}
发布评论

评论列表(0)

  1. 暂无评论