2017-02-01 9 views
0

ich versuche, zweimal zu öffnen Transaktion ein EntityManager mit:Kann nicht Transaktion EntityManger mit wieder öffnen

EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU"); 
     EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 
     em.close(); 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 
     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 
     em.close(); 

und eine Ausnahme erhalten:

i

Exception in thread hier bin " main "java.lang.IllegalStateException: or[email protected]31e4bb2020 ist geschlossen

Meine Vermutung ist: Es ist nicht möglich, eine andere Transaktion aus dem geschlossenen EntityManager zu bekommen. Allerdings JPA Spec sagt:

EntityManager.close Methode ein Unternehmen Manager Kontext und andere Ressourcen freizugeben, seine Beharrlichkeit schließt. Nach dem Aufruf von close darf die Anwendung keine weiteren Methoden auf der EntityManager Instanz außer getTransaction und isOpen aufrufen, oder die IllegalStateException wird geworfen. Wenn die Methode close aufgerufen wird, wenn eine Transaktion aktiv ist, bleibt der Persistenzkontext bis zum Abschluss der Transaktion bestehen.

Könnte jemand erklären, wo ich falsch liege? gibt es keine Möglichkeit zum Aufruf getTransaction bedeuten, dass ich diese Transaktion und ivoke Transaktion Methoden verwenden kann?

Vielen Dank.

UPDATE

Danke für die Antworten, sind diese sehr hilfreich für mich:

1:

Sie die EntityManager verwenden können, bis Sie in der Nähe nennen, ja. Es gibt keine "reopen" Methode. einen EntityManager zu schaffen, ist ein billiger Betrieb - Neil 13 Minuten Stockton vor

2:

Sie getTransaction anrufen um zu überprüfen, ob eine Transaktion aktiv ist. Yu könnte auch einen EntityManager mit einem aktiven TX schließen (wie der Docs-Status ) und nach dem Schließen commit). Daher die Tatsache, dass Sie getTransaction aufrufen können. - M. Deinum 9 Minuten vor

+1

Die Dokumente sind ziemlich klar .... * Die Anwendung darf keine weiteren Methoden in der EntityManager-Instanz aufrufen außer getTransaction und isOpen, * ... Sie versuchen, etwas mit einem geschlossenen Entity-Manager beizubehalten, was nicht der Fall ist dürfen. Sie sollten den Entity Manager nur einmal kurz aufrufen. –

+0

ok, aber was ich nicht verstehen kann, warum kann ich getTransaction aufrufen und dann nicht verwenden? –

+0

Warum würden Sie den EntityManager schließen und dann versuchen, irgendeine Methode darauf aufzurufen ?! geschweige denn versuchen, es später wieder zu schließen! –

Antwort

1

Die Realität hier ist, dass Ihre erste close() -Aufruf nicht notwendig ist. Was Sie effektiv erreichen wollen, ist, zwei isolierte Transaktionen zu haben - vollkommen gültig. Es gibt zwei grundlegende Möglichkeiten, dies zu tun.

1) Übernehmen Sie die Transaktion, und starten Sie eine neue Instanz in derselben Entity Manager-Instanz.Ein Beispiel, wo ich Vertiefung Missbrauch zu zeigen, wie lange die Einheit Manager leben:

EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 

     // no close here 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 
     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 

em.close(); 

2) das Unternehmen Manager schließen und einen neuen erstellen (die als in den Kommentaren gesagt, recht billig)

EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 

em.close(); 


// create new EntityManager 
em = emf.createEntityManager(); 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 

     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 

em.close(); 

Welche Option Sie wählen, hängt vom weiteren Design der Anwendungsfunktion ab, zu der es gehört. Option 1) ist zum Beispiel cachefreundlicher und wird wahrscheinlich den Cache der ersten Ebene zwischen den Transaktionen beibehalten. Dies birgt das Risiko, dass zwischengespeicherte Entitäten im Cache veralten, wenn zwischen den Transaktionen und den Datenänderungen in der Datenquelle eine Verzögerung auftritt, die ein Aufruf an em.clear() zwischen Transaktionen beheben kann.

Ich neige dazu, für Option 2), wenn ich die Transaktions-Batching-Logik implementieren, sagen: Datei-Import-Logik, die in großen Mengen von Datensätzen pumpt, die verarbeitet und in kleineren Brocken begangen werden. In jedem anderen Fall funktioniert die Option 1) in der Regel gut.

-1

Probieren Sie die folgenden Änderungen an Ihrem Code machen:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU"); 
     EntityManager em = emf.createEntityManager(); 

    Message message0 = new Message(); 
    em.getTransaction().begin(); 
    message0.setText("Hi!!"); 
    em.persist(message0); 
    em.getTransaction().commit(); 
    em.close(); 
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("HelloWorldPU"); 
      EntityManager em1 = emf.createEntityManager(); 
    Message message1 = new Message(); 
    em1.getTransaction().begin(); 
    message1.setText("Bye!!"); 

    System.out.println("i'm here"); 

    em1.persist(message1); 
    em1.getTransaction().commit(); 
    em1.close(); 

Try and zurückkehren Sobald EM geschlossen ist, sollten Sie erstellen/öffnen ein neues!.

+0

Wenn Sie einen EMF mehrere Male erstellen, wird Ihre Anwendung sehr langsam laufen !!! Auch Sie schließen Ihren EMF dort nicht ... –

Verwandte Themen