Ich habe Probleme mit einer von Hibernate geworfenen NonUniqueObjectException
.
Beim Lesen der Dokumente und dieses Blogposts habe ich den Aufruf von update()
an merge()
ersetzt und das Problem gelöst.
Ich glaube, ich verstehe den Grund für die Ausnahme und warum das Ändern der Methode das Problem in Bezug auf getrennte Objekte und Sitzungsgrenzen behoben hat.
Meine Frage ist: Wenn merge()
immer zum Sitzungsobjekt aufgelöst wird oder es abruft, wenn es nicht existiert, ist der Aufruf von merge () im Allgemeinen eine sicherere Alternative als update()
?
Was ist der Nachteil der Verwendung von merge()
über update()
?
Ist der Aufruf von merge () generell eine sicherere Alternative als update ()?
Ja, um NonUniqueObjectException zu vermeiden. Ich denke, es erklärt, warum JPA keine Aktualisierungsmethode zulässt.
Was ist der Nachteil von merge () über update ()?
Ein nicht empfohlener Benutzer könnte denken, dass er oder sie eine neue verwaltete Entität hat. So etwas wie
// myEntity (passed as parameter does not become managed)
// Only the one returned by the merge operation is a managed entity
session.merge(myEntity);
// "newValue" is not commited because myEntity is not managed
myEntity.setMyProperty("newValue");
Und wenn Ihr Persistenzkontext Ihre Entität nicht enthält, ist möglicherweise möchten Sie nicht vor dem Aktualisieren auswählen Standardverhalten. Aber es kann vermieden werden
...
public void updateMyEntity(MyEntity updateableMyEntity);
// load does not hit the database
MyEntity myEntity = (MyEntity) session.load(MyEntity.class, updateableMyEntity.getId());
BeanUtils.copyProperties(myEntity, updateableMyEntity);
}
Auf diese Weise können Sie Ihre Entität ohne Zusammenführungs- oder Aktualisierungsmethode aktualisieren. Weitere Informationen finden Sie in dieser Frage: Bester Weg, um einige Felder eines freistehenden Objekts auf Hibernate zu aktualisieren?
Verwenden Sie update (), wenn Sie sicher sind, dass die Sitzung keine bereits beständige Instanz mit demselben Bezeichner enthält, und merge (), wenn Sie Ihre Änderungen jederzeit ohne Rücksicht auf den Status der Sitzung zusammenführen möchten. Mit anderen Worten, update () ist in der Regel die erste Methode, die Sie in einer neuen Sitzung aufrufen würden, um sicherzustellen, dass das Wiederanfügen Ihrer getrennten Instanzen die erste ausgeführte Operation ist.
SessionFactory factory = cfg.buildSessionFactory();
Session session1 = factory.openSession();
Student s1 = null;
Object o = session1.get(Student.class, new Integer(101));
s1 = (Student)o;
session1.close();
s1.setMarks(97);
Session session2 = factory.openSession();
Student s2 = null;
Object o1 = session2.get(Student.class, new Integer(101));
s2 = (Student)o1;
Transaction tx=session2.beginTransaction();
session2.merge(s1);
Erklärung
Wie aus den Zeilennummern 4–7 hervorgeht, haben wir gerade ein Objekt s1 in den Cache von session1 geladen und session1 in Zeile 7 geschlossen. Das Objekt s1 im Cache von session1 wird also zerstört, da der Cache von session1 abläuft, wenn wir session1.close()
sagen.
Das s1-Objekt befindet sich jetzt an einem bestimmten Ort RAM, nicht im Cache von session1. Hier befindet sich s1 im getrennten Zustand, und in Zeile 8 haben wir das abgetrennte Objekt s1 geändert. Wenn wir nun die update()
-Methode aufrufen, wird im Ruhezustand ein Fehler ausgegeben, da das Objekt nur in der Sitzung aktualisiert werden kann.
Also eröffneten wir eine weitere Session [session2] in Zeile 10 und luden wieder das gleiche Schülerobjekt aus der Datenbank, jedoch mit dem Namen s2. In dieser Session2 haben wir session2.merge(s1);
aufgerufen, und nun werden in s2 object s1 Änderungen zusammengeführt und in der Datenbank gespeichert