JPA-Verwirrung (verwaltete vs nicht verwaltete Entitäten)

8

Ich arbeite an einem Web-Projekt und versuche, den besten Weg zu finden, so etwas immer wieder zu tun:

  • Lesen Sie das Objekt A aus dem DB
  • Lesen Sie später ein anderes Objekt ( B )
  • Nehmen Sie Änderungen an A und B in der DB vor (als Teil einer Transaktion - schreiben Sie all die Änderungen oder keine)

Der old-skool JDBC-Typ ist kein Problem, aber JPA macht meinen Kopf.

Ich brauche eine klare Abgrenzung darüber, wo die DB-Änderungen auftreten, und nach dem, was ich beobachtet habe, werden Änderungen an verwalteten Entitäten beim nächsten Aufruf von EntityManager.commit() geändert (unabhängig davon, ob eine Transaktion explizit war) vor den Änderungen begonnen oder nicht). Korrekt?

Ist es dann besser, sicherzustellen, dass alle Entitäten nie verwaltet werden und immer merge() ?

Ich muss mich zwischen diesen beiden Beispielen entscheiden:

RepaintAction1

%Vor%

RepaintDAO1

%Vor%

Oder:

RepaintAction2 (das ist dasselbe wie RepaintAction1 , aber mit verwalteten -Entitäten)

%Vor%

RepaintDAO2

%Vor%

Das erste macht mir nichts aus, aber ich muss einige Vorteile für verwaltete Entitäten (welche?) vermissen. In der zweiten mag ich nicht, wie der Umfang der Transaktionen nicht klar ist (und wie wird ein Rollback behandelt?).

Aber sind dies die einzigen Optionen (z. B. gibt es eine Möglichkeit, Transaktionen mit verwalteten Einheiten klar abzugrenzen)? Was ist der beste Weg, damit umzugehen?

Ich entschuldige mich dafür, dass ich das lange gemacht habe, aber ich habe eine Menge Dokumentation durchgelesen, die nicht geholfen hat, und ich bin mir nicht einmal sicher, dass das, was ich beobachte, korrekt ist.

    
Ivan Maeder 15.09.2011, 16:18
quelle

2 Antworten

11
  1. Änderungen an verwalteten Entitäten werden beim nächsten Aufruf von EntityManager.commit() geändert (unabhängig davon, ob eine Transaktion explizit vor den Änderungen begonnen wurde oder nicht). Korrigieren? Korrigieren.

  2. Ist es besser, sicherzustellen, dass alle Entitäten nie verwaltet werden und immer merge() ? Nicht immer (oder sie würden die Wahl nicht offen lassen), aber es ist üblich, Also Beispiel 1 ist das, was Sie am meisten finden.

  3. Der Flush in Beispiel 2 wird nicht wirklich benötigt, das Commit wird implizit flush.

  4. Wie wird das Rollback behandelt? Wenn die Übertragung fehlschlägt, wird der Persistenzanbieter zurückgesetzt. Ein Anwendungscontainer wird vorhandene Transaktionen zurücksetzen, wenn er eine Systemausnahme erhält.

  5. Vorteile von verwalteten Entitäten? Lazy-Laden (keine LazyInitializationException). Außerdem wird festgehalten, was sich für Sie geändert hat, sodass Sie nicht zu viele / wenige Entitäten zusammenführen.

  6. Gibt es eine Möglichkeit, Transaktionen mit verwalteten Einheiten klar abzugrenzen? Es ist mir nicht klar, was Ihnen nicht klar ist. Vielleicht meinen Sie, dass es nicht klar ist, was sich geändert hat, weil die Änderungen an den Entitäten außerhalb der Start- / Commit-Grenzen stattfinden. Aber das gilt auch für das Zusammenführen von getrennten Entitäten. Sie haben ein wenig mehr Kontrolle darüber, was Sie zusammenführen, aber Sie sehen nicht genau, welche Attribute geändert werden.

  7. Was ist der beste Weg, um damit umzugehen? Normalerweise werden Ihre Web-Anfragen von einem transaktionalen Service abgewickelt (spring / ejb ...). Entity Manager werden vom Container injiziert. In der Regel sind diese Entity Manager transaktionsspezifisch (nur für die Dauer der Transaktion aktiv). Sie waren also nicht vorhanden, bevor Ihr Service aufgerufen wurde. Dies bedeutet, dass alle an sie übergebenen Entitäten nicht verwaltet werden. Die Transaktion wird am Ende des Dienstes festgeschrieben (oder rückgängig gemacht).

Hinweis: Wenn Sie verwaltete Entitäten verwenden, ist dies oft mit langlebigen EntityManagern verbunden. Wenn Sie dies tun, beachten Sie, dass EntityManagers nicht Thread-sicher sind.

    
Catweazle 17.09.2011, 09:29
quelle
0

Im Hinblick auf Ihre vierte Frage kann Rollback auf folgende Weise durchgeführt werden:

  1. Wirf eine Ausnahme von der Methode, die als @Transactional
  2. markiert ist
  3. Sagen Sie der Transaktion explizit, dass sie von TransactionAspectSupport.currentTransactionStatus () zurückgesetzt werden soll. setRollbackOnly ();
Shahar Wiener 21.07.2015 14:34
quelle

Tags und Links