2010-07-27 8 views
5

hay 19 métodos en nuestra capa DAO, cada uno es alguna variación de esto:¿Cuál es la forma correcta de garantizar que las conexiones de EntityManager estén cerradas?

public TicketProp saveTicketProp(TicketProp prop) { 
    EntityManager em = this.emf.createEntityManager(); 
    try { 
     em.getTransaction().begin(); 
     prop = (TicketProp) em.merge(prop); 
     em.getTransaction().commit(); 
     return prop; 
    } finally { 
     em.close(); 
    } 
} 

Significado: En cada método en que manejamos nuestra propia transacción y cerrarlo en un bloque finally. Estamos probando una aplicación de Jersey, por lo que nuestras pruebas JUnit extienden JerseyTest. Cada método de prueba instancia un contenedor Grizzly, ejecuta la prueba y luego cierra el contenedor. EntityManagerFactory se inyecta en primavera. Estamos usando JPA sobre Hibernate.

Estoy monitoreando las conexiones a nuestro banco de pruebas MySQL y siempre son altas. Una sola prueba ejecuta la variable "Max_used_connections" de MySQL a 38. Para divertirme, comenté todas las llamadas a em.close() y la prueba todavía usa 38 conexiones.

Estoy utilizando la agrupación de conexiones integrada de Hibernate (no para el uso de prod, lo sé). Todavía esperaba algún tipo de agrupación inteligente.

¿Manejo incorrecto el EntityManager? ¿De qué otra forma puedo cerrar las conexiones?

+0

em.close sólo se libera la conexión a la agrupación de conexiones. emf.close cerrará todas las conexiones. por lo que puede haber demasiada fem creando en su aplicación, por lo que tiene demasiadas conexiones. – Scarlett

Respuesta

2

¿Por qué crees que EntityManager.close() siempre cierra físicamente la conexión subyacente? Depende del grupo de conexiones (probablemente necesite configurarlo y establecer el número máximo de conexiones abiertas simultáneamente).

5

Usted debe closeEntityManagerFactoryal final de su prueba. Desde el javadoc de EntityManagerFactory#close():

void javax.persistence.EntityManagerFactory.close() 

cerrar la fábrica, la liberación de todos los recursos que posee. Después de que se haya cerrado una instancia de fábrica, todos los métodos invocados arrojarán el IllegalStateException, excepto el isOpen, que devolverá falso. Una vez que se ha cerrado EntityManagerFactory, se considera que todos sus administradores de entidades están en estado cerrado.

Como nota al margen, en realidad se debe deshacer la transacción antes de cerrar la EM en la cláusula finally:

public TicketProp saveTicketProp(TicketProp prop) { 
    EntityManager em = this.emf.createEntityManager(); 
    try { 
     em.getTransaction().begin(); 
     prop = (TicketProp) em.merge(prop); 
     em.getTransaction().commit(); 
     return prop; 
    } finally { 
     if (em.getTransaction().isActive()) { 
      em.getTransaction().rollback(); 
     } 

     if (em.isOpen()) { 
      em.close(); 
     } 
    } 
} 
+0

Las transacciones no se revertirán automáticamente en el caso de una excepción? ¿Mi bloqueo final lo impide? – gmoore

+2

@gmoore: en caso de una excepción JPA, sí. Pero, ¿y los demás? Considero que llamar al rollback en el bloque finally es una buena práctica. –

+0

sí, em.close solo libera la conexión al grupo de conexiones. emf.close cerrará todas las conexiones. por lo que puede haber demasiada fem creando en su aplicación, por lo que tiene demasiadas conexiones. – Scarlett

Cuestiones relacionadas