JPA Lifecycle Events

Lifcycle Event Aufrufe können mitunter etwas verwirrend sein, wie ich jüngst feststellen durfte. In folgendem Beispiel nehmen wir eine einfache OneToMany Relation:

Klassendiagramm

Hierbei sind die onSave Methoden jeweils als Livecyclelistener annotiert:

@PrePersist
@PreUpdate
private void onSave() {
    System.out.println("about to save MainEntity " + id);
}

Weiterhin ist die Relation zu SubEntities mit CascadeAll in MainEntity annotiert, damit die Abhängigen Entities automatisch gespeichert werden.

Zum Testen erzeugen wir als erstes einmal eine MainEntity mit einer SubEntity:

MainEntity me = new MainEntity(Long.valueOf(1)); // Id
Collection col = new ArrayList();
col.add(new SubEntity(me));
me.setSubEntities(col);
System.out.println("persisting...");
persist(me); // do persist stuff

Bei dem Aufruf wird zuerst der PrePersist Callback von MainEntity und danach von SubEntity. Die Ausgabe des Programms ist:

persisting...
about to save MainEntity 1
about to save SubEntity 1

Das ist auch genau das, was ich erwartet hätte. So könnte man vor dem Speichern die Abhängigen Collections aufräumen (z.B. die Rückrelation zu MainEntity eintragen).

Als nächstes erweitern wir das Programm um einen merge Aufruf. Vor dem Merge wird eine neue Entity zu der Collection zugefügt.

col.add(new SubEntity(me));
System.out.println("merging...");
merge(me);

Die Ausgabe des Programms für diesen Teil ist:

merging...
about to save SubEntity null
about to save MainEntity 1

Ups, das war nicht das, was ich erwarten würde. Wenn zu einer Existierenden Entity ein weiteres Element zu der OneToMany Collection zugefügt wird, so wird der Entsprechende Callback vor dem UpdateCallback der MainEntity aufgerufen.
Damit hat sich die Idee vom automatischen aufräumen von Collections erledigt.
Das Ganze funktioniert genau so, wenn eine attached MainEntity um eine SubEntity erweitert wird. Werden hingegen nur SubEntities, die bereits existieren aktualisiert, wird der Callback für diese erst nach der MainEntity aufgerufen.
Getestet mit TopLink und EclipseLink mit identischen Ergebnissen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *


7 × sechs =