web-dev-qa-db-de.com

Ruhezustand: Nachteil der Zusammenführung () über Update ()

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()?

29
Marty Pitt

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

  • Fügen Sie eine Versionsspalte (@Version) hinzu. 0 oder NULL-Version zeigt an, dass eine Instanz neu ist und muss eingefügt werden, nicht aktualisiert
  • Verwenden Sie einen Hibernate-Interceptor
  • Wenn Sie sicher sind, dass Sie aktualisieren möchten, anstatt einzufügen, können Sie den folgenden Ansatz verwenden

...

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?

41
Arthur Ronald

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.

4
Mark R
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

0
Ajit Deswal