Leakage of connections with Hibernate

2

My system had sporadic crashes and I discovered that this happened due to processes that opened a connection but, due to some error, they did not close it (connection leak).

I solved involving the problematic code in try/catch and forcing it to close in finally

My question is: Is there any way to prevent this leak or some timeout setting where, after some downtime, the connection is returned / closed?

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence      http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="udPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>br.com.xpto.etc</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
      <property name="hibernate.show_sql" value="false"/>
      <property name="hibernate.format_sql" value="false"/>
      <property name="hibernate.multiTenancy" value="SCHEMA"/>
      <property name="hibernate.tenant_identifier_resolver" value="br.com.multitenant.SchemaResolver"/>
      <property name="hibernate.multi_tenant_connection_provider" value="br.com.multitenant.MultiTenantProvider"/>
      <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
      <property name="hibernate.c3p0.acquire_increment" value="2"/>
      <property name="hibernate.c3p0.iddle_teste_period" value="70"/>
      <property name="hibernate.c3p0.max_size" value="15"/>
      <property name="hibernate.c3p0.max_statements" value="0"/>
      <property name="hibernate.c3p0.min_size" value="1"/>
      <property name="hibernate.c3p0.timeout" value="60"/>
    </properties>
  </persistence-unit>
</persistence>

EntityManagerFactory

public class FabricaEntityManager {

    private static FabricaEntityManager INSTANCE;
    private static EntityManagerFactory emf;
    private final static Logger log=Logger.getLogger(FabricaEntityManager.class);

    private FabricaEntityManager() {}

    public static FabricaEntityManager getInstance() {
        if (INSTANCE == null) {
                synchronized (FabricaEntityManager.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new FabricaEntityManager();
                        log.debug("Nova Fabrica");
                    }
                }
            }
        return INSTANCE;
    }

    public EntityManagerFactory getEntityManagerFactory(){
        if (emf==null){
            emf=Persistence.createEntityManagerFactory("udonlinePU");
            log.debug("Create EMF");
        }
        return emf;
    }
}

Transaction example

public EntityManager getEntityManager(){
        if (manager == null || !manager.isOpen()) {
            manager=FabricaEntityManager.getInstance().getEntityManagerFactory().createEntityManager();
            log.debug(">> CreateEntityManager");
        }
        return manager;
    }
public List<Despesa> getByAll(){
        Query qry=getEntityManager().createQuery("select d from Despesa d ");
        List<Despesa> rs = qry.getResultList();
        getEntityManager().close();
        return rs;
    }
    
asked by anonymous 05.02.2015 / 16:31

1 answer

1

The right way is to use some global solution for transaction control. I can remember 3 now:

  • Use the default OpenSessionInView: This way you will have a FilterWeb that upon receiving the request would open a connection, and when finished would close. This would be done with the try / finally that you created to solve the other problem.
  • With EJB - If you are using a server that has EJB, let EJB take care of the transaction for you.
  • With Spring - Use Spring and let it handle the transaction for you.
  • If you do not use a framework / standard that controls the transaction you will have to try / finally in all your methods.

    NOTE: Connection pool only serves to give you the connection, and nothing else. OBS2: I have honestly never seen a configuration that killed a particular connection that is active at X time. This err is usually bad programming practice.

        
    05.02.2015 / 20:59