2010-07-27 4 views
5

19 Methoden in unserer DAO Schicht Es gibt jeweils eine gewisse Variation dieses:Wie können EntityManager-Verbindungen ordnungsgemäß geschlossen werden?

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(); 
    } 
} 

Bedeutung: Bei jedem Verfahren wir unsere eigene Transaktion handhaben und schließen Sie es in einen finally-Block. Wir testen eine Jersey-App, daher erweitern unsere JUnit-Tests JerseyTest. Jede Testmethode instanziiert einen Grizzly-Container, führt den Test aus und fährt den Container dann herunter. EntityManagerFactory wird im Frühling injiziert. Wir verwenden JPA über Hibernate.

Ich überwache die Verbindungen zu unserer MySQL-Test-DB und sie sind immer hoch. Bei einem Test wird die MySQL-Variable "Max_used_connections" auf 38 gesetzt. Um Spaß zu haben, habe ich alle Aufrufe von em.close() auskommentiert, und der Test verwendet immer noch 38 Verbindungen.

Ich benutze Hibernate eingebaute Verbindungspooling (nicht für Prod verwenden, ich weiß). Ich erwartete immer noch eine Art von intelligentem Pooling.

Behandle ich den EntityManager falsch? Wie sonst kann ich Verbindungen schließen?

+0

em.close nur freigeben, um die Verbindung zu Verbindungspool. emf.close schließt alle Verbindungen. Es kann also sein, dass zu viel emf in der Anwendung erzeugt wird, also zu viele Verbindungen. – Scarlett

Antwort

2

Warum denken Sie, dass EntityManager.close() die zugrunde liegende Verbindung immer physisch schließt? Es ist der Verbindungspool (Sie müssen ihn wahrscheinlich konfigurieren und die maximale Anzahl gleichzeitig geöffneter Verbindungen festlegen).

5

Sie sollten close die EntityManagerFactoryam Ende Ihres Tests. Vom javadoc von EntityManagerFactory#close():

void javax.persistence.EntityManagerFactory.close() 

Schließen der Fabrik, die Freigabe aller Ressourcen, die sie hält. Nachdem eine Factory-Instanz geschlossen wurde, werden alle aufgerufenen Methoden die IllegalStateException auslösen, mit Ausnahme von isOpen, die false zurückgibt. Sobald ein EntityManagerFactory geschlossen wurde, werden alle Entitätsmanager als geschlossen betrachtet.

Als Randbemerkung, sollten Sie die Transaktion Rollback tatsächlich die EM in der finally Klausel vor der Schließung:

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

Transaktionen werden im Falle einer Ausnahme nicht automatisch zurückgesetzt? Blockiert mein Block das letztendlich? – gmoore

+2

@gmoore: Im Falle einer JPA-Ausnahme ja. Aber was ist mit anderen? Ich halte Rollback im finally Block für eine gute Übung. –

+0

ja, em.schließen Sie nur die Verbindung zum Verbindungspool frei. emf.close schließt alle Verbindungen. Es kann also sein, dass zu viel emf in der Anwendung erzeugt wird, also zu viele Verbindungen. – Scarlett