Training, Workshops, Softwareentwicklung

Hibernate Tutorial

Merge

Wir haben gesehen, dass Änderungen an einem Objekt, das dem EntityManager bekannt ist, automatisch am Ende einer Transaktion gespeichert werden.

Was tun, wenn wir ein Objekt speichern wollen, das dem EntityManager nicht bekannt ist?

Wir benötigen etwas, das in etwa so funktioniert:

Customer customerOutside = getCustomer();

// what if customerOutside has changed ?
customerOutside.setFirstname("Alice");

saveCustomer(customerOutside);

doInHibernate(em -> {

    Customer customer = em.find(Customer.class, 1L);

    assertNotNull(customer);
    assertEquals("Alice", customer.getFirstname());

    withTransaction(em, () -> customer.setFirstname("Buck"));

});

In vielen Projekten findet man eine Methode, die so (oder so ähnlich) aussieht:

save()
private void saveCustomer(Customer customerOutside) {
    doInHibernate(em -> {
        withTransaction(em, () -> {
            Customer customerMerged = em.merge(customerOutside);
        });
    });
}

Jetzt möchte man meinen, dass merge das Objekt speichert. Dem ist aber überhaupt nicht so. Die merge Operation verbindet lediglich ein bestehendes Objekt mit einem neuen EntityManager.

Ein gern (auch von mir immer wieder) gemachter Fehler ist dabei, dass das Objekt selbst tatsächlich nicht mit dem EntityManager verbunden wird, sondern, dass die Funktion eine Kopie erstellt und zurückliefert. (Hier: customerMerged). Dieses neue Objekt ist nach dem merge mit dem EntityManager verbunden.

Es wurde aber noch nicht gespeichert!! Erst wenn die Transaktion abgeschlossen wird, wird ein flush ausgelöst, der wie gewohnt nach Änderungen sucht und diese persistiert.

Die einzelnen Schritte seht Ihr im Screencast: