Verwendung von JPA-Lebenszyklusereignissen zum Abrufen von Entitätsdaten

8

Ich habe eine RESTful-API, die eine mit @EntityListners annotierte Entitätsklasse verwendet. Und in der EntityListner.java habe ich eine Methode mit @PostPersist kommentiert. Wenn also dieses Ereignis ausgelöst wird, möchte ich alle Informationen bezüglich der Entität extrahieren, die gerade in der Datenbank erhalten geblieben ist. Aber wenn ich das versuche, erzeugt Glassfish eine Ausnahme und die Methode in der EntityListner-Klasse wird nicht wie erwartet ausgeführt. Hier ist der Code

%Vor%

Wenn ich die auskommentierte successMessage Nachricht anstelle von custData sende, funktioniert alles einwandfrei.

Ссылка sagt Folgendes zu den Entity Lifecycle-Methoden, und ich frage mich, ob das der Fall ist hier.

  

Um Konflikte mit der ursprünglichen Datenbankoperation zu vermeiden, die das Entity-Lifecycle-Ereignis auslöst (das noch läuft), sollten Callback-Methoden keine EntityManager- oder Query-Methoden aufrufen und nicht auf andere Entitätsobjekte zugreifen

Irgendwelche Ideen?

    
Abraham 28.10.2012, 08:19
quelle

3 Antworten

8

Wie dieser Absatz sagt, unterstützt der Standard das Aufrufen von Entity Manager-Methoden nicht innerhalb von Entity-Listenern. I stark empfehle den Aufbau von custData von der persistenten Entität, wie Heiko Rupp in seiner Antwort sagt. Wenn das nicht möglich ist, überlegen Sie:

  • benachrichtigt asynchron. Ich empfehle das nicht wirklich , da es wahrscheinlich vom Timing abhängt, ob es richtig funktioniert:
%Vor%
  • Registrierung eines Post-Commit-Triggers (meine Empfehlung, wenn Heilo Rupp keine Antwort geben kann). Dies ist nicht zeitabhängig, da es garantiert ausgeführt wird, nachdem Sie in die Datenbank geleert haben. Darüber hinaus hat es den zusätzlichen Vorteil, dass Sie nicht benachrichtigt werden, wenn Sie Ihre Transaktion rückgängig machen. Die Art, dies zu tun, hängt davon ab, was Sie für die Transaktionsverwaltung verwenden, aber im Grunde erstellen Sie eine Instanz einer bestimmten Instanz und registrieren sie dann in einer Registrierung. Zum Beispiel mit JTA wäre es:
%Vor%

Wenn Sie Spring-Transaktionen verwenden, ist der Code sehr ähnlich, mit nur einigen Änderungen des Klassennamens.

Einige Hinweise:

gpeche 18.12.2012, 20:45
quelle
3

Ich nehme an, dass Sie möglicherweise eine NPE sehen, da Sie möglicherweise den von Ihnen zitierten Absatz verletzen:

%Vor%

Das find scheint implizit nach dem Objekt zu suchen (wie Sie es beschreiben), das nicht vollständig mit der Datenbank synchronisiert und daher noch nicht zugänglich ist.

    
Heiko Rupp 28.10.2012 08:25
quelle
1

In seiner Antwort bemerkte Gpeche, dass es ziemlich einfach ist, seine Option # 2 in Spring zu übersetzen. Um anderen die Mühe zu ersparen:

%Vor%

Die Servicemethode (hier, updateEndpoints() ) kann die JPA EntityManager (in meinem Fall Abfragen und Aktualisierungselemente) ohne Probleme verwenden. Achten Sie darauf, die updateEndpoints() -Methode mit @Transaction(propagation = Propagation.REQUIRES_NEW) zu kommentieren, um sicherzustellen, dass eine neue Transaktion zum Ausführen der Persistenzvorgänge vorhanden ist.

Nicht direkt mit der Frage verbunden, aber ApplicationContextProvider ist nur eine benutzerdefinierte Klasse, die einen App-Kontext zurückgibt, da JPA 2.0-Entity-Listener keine verwalteten Komponenten sind und ich zu faul bin, hier @Configurable zu verwenden. Hier ist es der Vollständigkeit halber:

%Vor%     
Willie Wheeler 13.05.2014 01:41
quelle