Ich benutze EclipseLink 2.3.0. Ich habe eine Methode, die ich von einem Unit-Test anzurufenden (also außerhalb eines Behälters, kein JTA), die wie folgt aussieht:JPA/EclipseLink: Erstellt EntityManager.getTransaction() eine neue Transaktion oder gibt die aktive zurück?
EntityManager em = /* get an entity manager */;
em.getTransaction().begin();
// make some changes
em.getTransaction().commit();
Die Änderungen wurden nicht in die Datenbank beibehalten wird, und suchte eine auf diese Lange Zeit und schließlich erkannt, dass EntityManager.getTransaction() tatsächlich eine neue EntityTransaction zurückgibt, anstatt die gleiche in beiden Aufrufen. Der Effekt besteht darin, dass der erste Aufruf eine neue Transaktion erstellt und beginnt, und der zweite Aufruf eine ANDERE Transaktion erstellt und festschreibt. Da die erste Transaktion nie festgeschrieben wurde, werden die Änderungen nicht gespeichert. Wir bestätigten dies wie folgt aus:
log.info(em.getTransaction().toString());
log.info(em.getTransaction().toString());
, die in diesen Protokollmeldungen zur Folge:
INFO: org.ecl[email protected]1e34f445
INFO: org.ecl[email protected]706a4d1a
Die beiden unterschiedlichen Objekt ID überprüfen, ob es zwei verschiedene Instanzen. Ändern des Codes zu diesem:
EntityManager em = /* get an entity manager */;
EntityTransaction tx = em.getTransaction();
tx.begin();
// make some changes
tx.commit();
... das Problem behoben. Jetzt, wenn ich den Code ausführe, sehe ich die SQL-Anweisungen generiert, um die Datenbank arbeiten zu tun, und in der Datenbank suchen, wurden die Daten geändert.
Ich war ein bisschen überrascht von diesem Ergebnis, da ich zahlreiche Code-Beispiele online (für JPA allgemein und speziell für EclipseLink) gesehen habe, die den Code empfehlen, den wir für die Verwaltung von Transaktionen verwendeten. Ich habe weit und breit gezielt nach Informationen gesucht, aber nichts gefunden. So was ist los?
Ich sah in der JPA-Spezifikation für etwas, das genau angibt, was getTransaction() tut und es war nicht spezifisch, ob die Transaktion neu oder gleich ist. Gibt es eine Einstellung in persistence.xml, die dies steuert? Ist das Verhalten für jede Implementierung der JPA-Spezifikation spezifisch?
Vielen Dank für jede Information oder Anleitung.
Vielleicht hätte ich klarer sein sollen - der Code, den ich gepostet habe funktioniert nicht. Ich habe die Frage bearbeitet, um sie zu klären. –
Ich verstehe das. Mein Punkt ist, dass es * funktionieren sollte *, da die JPA-Spezifikation Code-Beispiele enthält, wenn 'em.getTransaction()' verwendet wird, um die Transaktion zu beginnen und zu committen. Es muss also ein Fehler in EclipseLink sein, es sei denn, wie gesagt, der Code zwischen dem Beginn und dem Commit setzt die Transaktion bereits fest oder führt einen Rollback durch. Meine Antwort ist keine Lösung für Ihr Problem, sondern eine Bestätigung, dass der Code funktionieren sollte. Ich schlage vor, einen Fehler an EclipseLink zu senden. –