JPA EntityManager: po co używać persist () nad merge ()?

EntityManager.merge() może wstawiać nowe obiekty i aktualizować istniejące.

Dlaczego warto używać persist() (które mogą tworzyć tylko nowe obiekty)?

Author: Harshal Patil, 2009-07-01

15 answers

Tak czy inaczej doda encję do PersistenceContext, różnica polega na tym, co robisz z encją później.

Persist pobiera instancję encji, dodaje ją do kontekstu i sprawia, że ta instancja jest zarządzana (tzn. przyszłe aktualizacje encji będą śledzone).

Merge tworzy nową instancję encji, kopiuje stan z dostarczonego encji i sprawia, że nowa kopia jest zarządzana. Przekazywana instancja nie będzie zarządzana (wszelkie wprowadzone zmiany nie będą częścią transakcja-chyba, że ponownie wywołasz merge).

Może przykład kodu pomoże.

MyEntity e = new MyEntity();

// scenario 1
// tran starts
em.persist(e); 
e.setSomeField(someValue); 
// tran ends, and the row for someField is updated in the database

// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue); 
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)

// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue); 
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)

Scenariusz 1 i 3 są mniej więcej równoważne, ale są sytuacje, w których chciałbyś użyć scenariusza 2.

 1479
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-27 11:56:38

Persist i merge służą do dwóch różnych celów(w ogóle nie są alternatywami).

(edytowane w celu rozszerzenia informacji o różnicach)

  • wstaw nowy rejestr do bazy danych
  • Dołącz obiekt do menedżera encji.

Merge:

  • Znajdź dołączony obiekt o tym samym id i zaktualizuj go.
  • if exists update and return the already attached object.
  • Jeśli nie istnieje Dodaj nowy rejestr do baza danych.

Persist() wydajność:

  • może być bardziej wydajne wstawianie nowego rejestru do bazy danych niż merge ().
  • nie powiela oryginalnego obiektu.

Persist () semantyka:

  • upewnia się, że wstawiasz i nie aktualizujesz przez pomyłkę.

Przykład:

{
    AnyEntity newEntity;
    AnyEntity nonAttachedEntity;
    AnyEntity attachedEntity;

    // Create a new entity and persist it        
    newEntity = new AnyEntity();
    em.persist(newEntity);

    // Save 1 to the database at next flush
    newEntity.setValue(1);

    // Create a new entity with the same Id than the persisted one.
    AnyEntity nonAttachedEntity = new AnyEntity();
    nonAttachedEntity.setId(newEntity.getId());

    // Save 2 to the database at next flush instead of 1!!!
    nonAttachedEntity.setValue(2);
    attachedEntity = em.merge(nonAttachedEntity);

    // This condition returns true
    // merge has found the already attached object (newEntity) and returns it.
    if(attachedEntity==newEntity) {
            System.out.print("They are the same object!");
    }

    // Set 3 to value
    attachedEntity.setValue(3);
    // Really, now both are the same object. Prints 3
    System.out.println(newEntity.getValue());

    // Modify the un attached object has no effect to the entity manager
    // nor to the other objects
    nonAttachedEntity.setValue(42);
}

W ten sposób istnieje tylko 1 dołączony obiekt dla dowolnego rejestru w Menedżerze encji.

Merge () dla encji o id jest coś w stylu:

AnyEntity myMerge(AnyEntity entityToSave) {
    AnyEntity attached = em.find(AnyEntity.class, entityToSave.getId());
    if(attached==null) {
            attached = new AnyEntity();
            em.persist(attached);
    }
    BeanUtils.copyProperties(attached, entityToSave);

    return attached;
}

Chociaż jeśli połączenie z MySQL merge() może być równie wydajne jak persist() używając wywołania INSERT z opcją aktualizacji DUPLICATE KEY, JPA jest bardzo wysokim poziomem programowania i nie można zakładać, że będzie tak wszędzie.

 153
Author: Josep Panadero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-15 09:11:41

Jeśli używasz przypisanego generatora, używanie merge zamiast persist może spowodować redundantne polecenie SQL, wpływając tym samym na wydajność.

Również, wywołanie merge dla zarządzanych jednostek jest również błędem, ponieważ zarządzane jednostki są automatycznie zarządzane przez Hibernate, a ich stan jest synchronizowany z rekordem bazy danych przez mechanizm dirty checking po wypłukaniu kontekstu trwałości.

Aby zrozumieć, jak to wszystko działa, powinieneś najpierw wiedzieć, że Hibernate zmienia sposób myślenia programistów z instrukcji SQL na przejścia stanu encji .

Gdy encja jest aktywnie zarządzana przez Hibernate, wszystkie zmiany będą automatycznie propagowane do bazy danych.

Hibernate monitoruje aktualnie dołączone jednostki. Ale aby jednostka mogła być zarządzana, musi znajdować się we właściwym stanie podmiotu.

Najpierw musimy zdefiniować wszystkie stany encji:

  • New (Transient)

    A nowo utworzony obiekt, który nigdy nie był skojarzony z Hibernate Session (Aka Persistence Context) i nie jest mapowany do żadnego wiersza tabeli bazy danych, jest uważany za nowy (Transient) stan.

    Aby zostać wytrwałym, musimy albo jawnie wywołać metodę EntityManager#persist, albo skorzystać z mechanizmu transitive persistence.

  • Trwałe (Zarządzane)

    Stała jednostka została powiązana z wierszem tabeli bazy danych i jest zarządzana przez bieżące działanie Kontekst Wytrwałości. Każda zmiana taka jednostka zostanie wykryta i propagowane do bazy danych (podczas sesji flush-time). Dzięki Hibernate nie musimy już wykonywać poleceń INSERT/UPDATE/DELETE. Hibernate wykorzystuje styl pracy transactional write-behind , a zmiany są synchronizowane w ostatnim odpowiedzialnym momencie, podczas bieżącego Session flush-time.

  • Wolnostojący

    Po zamknięciu bieżącego kontekstu trwałości działania wszystkie wcześniej zarządzane podmioty stają się odłączone. Kolejne zmiany nie będą już śledzone i nie nastąpi automatyczna synchronizacja bazy danych.

    Aby powiązać odłączony obiekt z aktywną sesją hibernacji, możesz wybrać jedną z następujących opcji:

    • Reattaching

      Hibernate (ale nie JPA 2.1) obsługuje ponowne podłączenie za pomocą metody Session#update. Sesja hibernacji może kojarzyć tylko jeden obiekt Entity dla danego wiersza bazy danych. To jest ponieważ kontekst Persistence działa jako pamięć podręczna (pamięć podręczna pierwszego poziomu) i tylko jedna wartość (encja) jest powiązana z danym kluczem (Typ encji i identyfikator bazy danych). Encja może być ponownie dołączona tylko wtedy, gdy nie ma innego obiektu JVM (pasującego do tego samego wiersza bazy danych) skojarzonego z bieżącą sesją hibernacji.

    • Scalanie

    Połączenie skopiuje odłączony stan encji (źródło) do zarządzanej instancji encji (miejsce docelowe). Jeśli obiekt scalający nie ma odpowiednika w bieżącej sesji, jeden zostanie pobrany z bazy danych. Odłączona instancja obiektu pozostanie odłączona nawet po operacji scalania.

  • Usunięty

    Chociaż JPA wymaga, aby można było usuwać tylko zarządzane encje, Hibernate może również usuwać odłączone encje (ale tylko poprzez wywołanie metody session#delete). Usunięta jednostka jest zaplanowana tylko do usunięcia, a rzeczywiste polecenie usunięcia bazy danych będzie wykonywane podczas sesji flush-time.

Aby lepiej zrozumieć przejścia stanu JPA, możesz zwizualizować następujący diagram:

Tutaj wpisz opis obrazka

Lub jeśli używasz specyficznego dla Hibernate API:

Tutaj wpisz opis obrazka

 113
Author: Vlad Mihalcea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 06:22:59

Zauważyłem, że kiedy użyłem em.merge, otrzymałem SELECT polecenie dla każdego INSERT, nawet jeśli nie było pola generowanego przez JPA-głównym polem klucza był UUID, który sam ustawiłem. Przełączyłem się na em.persist(myEntityObject) i dostałem wtedy tylko INSERT wypowiedzi.

 37
Author: Sarah Vessels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 21:14:31

Specyfikacja JPA mówi co następuje o persist().

Jeśli X jest obiektem odłączonym, EntityExistsException może zostać wyrzucony, gdy operacja jest wywoływana, lub EntityExistsException lub inny {[3] } może być wyrzucony w czasie flush lub commit.

Więc użycie persist() byłoby odpowiednie, gdy obiekt nie powinien być odłączonym obiektem. Może wolisz, aby Kod wyrzucił PersistenceException, aby szybko się nie powiódł.

Chociaż specyfikacja jest niejasne, persist() może ustawić @GeneratedValue @Id na przedmiot. merge() jednak musi mieć obiekt z @Id już wygenerowany.

 28
Author: Raedwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:48

Kilka szczegółów na temat merge, które pomogą Ci użyć merge over persist:

Zwracanie zarządzanej instancji innej niż oryginalna jednostka jest krytyczną częścią scalania proces. Jeśli instancja podmiotu o tym samym identyfikatorze już istnieje w kontekście persistence, dostawca nadpisze swój stan stanem podmiotu, który jest łączony, ale zarządzany wersja, która już istniała, musi zostać zwrócona klientowi, aby mogła zostać użyta. Jeśli dostawca nie zaktualizuj instancję pracownika w kontekście persistence, wszelkie odniesienia do tej instancji staną się niespójne z połączeniem nowego państwa.

Kiedy merge() jest wywoływane na nowym obiekcie, zachowuje się podobnie do operacji persist (). Dodaje encja do kontekstu persistence, ale zamiast dodawać oryginalną instancję encji, tworzy nową zamiast tego kopiuje i zarządza tą instancją. Kopia tworzona przez operację merge() jest / align = "left" / tak jakby metoda persist() została na niej wywołana.

W obecności relacji, operacja merge() spróbuje zaktualizować zarządzany obiekt wskazywanie zarządzanych wersji podmiotów, do których odnosi się odrębny podmiot. Jeżeli jednostka ma relacji do obiektu, który nie ma trwałej tożsamości. wynikiem operacji scalania jest undefined. Niektórzy dostawcy mogą zezwolić kopii zarządzanej na wskazywanie obiektu nietrwałego, podczas gdy inni mogą rzucać wyjątek natychmiast. Operacja merge () może być opcjonalnie kaskadowe w takich przypadkach, aby zapobiec wystąpieniu wyjątku. Zajmiemy się kaskadowym połączeniem() operacja w dalszej części tej sekcji. Jeśli jednostka łączona wskazuje na jednostkę usuniętą, Wyjątek IllegalArgumentException zostanie wyrzucony.

Relacje Lazy-loading są szczególnym przypadkiem w operacji merge. Jeśli leniwy-Ładowanie związek nie został wywołany na jednostce przed jej odłączeniem, że związek będzie ignorowane podczas scalania encji. Jeśli relacja została uruchomiona podczas zarządzania, a następnie ustawiona na null, gdy encja została odłączona, zarządzana wersja encji będzie również miała relację wyczyszczoną podczas łączenia."

Wszystkie powyższe informacje zostały zaczerpnięte z "Pro JPA 2 Mastering the Java™ Persistence API" Mike ' a Keitha i Merricka Schnicariola. Rozdział 6. Sekcja odłączenie i łączenie. Ta książka jest właściwie drugą książką poświęconą JPA przez autorów. Ta nowa książka ma wiele nowych informacji niż poprzednia. Naprawdę polecam przeczytać tę książkę dla tych, którzy będą poważnie zaangażowani w JPA. Przepraszam za anonimowe zamieszczenie mojej pierwszej odpowiedzi.

 16
Author: Khurshed Salimov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 14:11:52

Jest jeszcze kilka różnic między merge i persist (wymienię jeszcze raz te już zamieszczone tutaj):

D1. merge nie sprawia, że przekazywany obiekt jest zarządzany, ale raczej zwraca inną instancję, która jest zarządzana. persist po drugiej stronie będzie zarządzany przekazywany podmiot:

//MERGE: passedEntity remains unmanaged, but newEntity will be managed
Entity newEntity = em.merge(passedEntity);

//PERSIST: passedEntity will be managed after this
em.persist(passedEntity);

D2. Jeśli usuniesz encję, a następnie zdecydujesz się przywrócić encję, możesz to zrobić tylko za pomocą persist (), ponieważ merge wyrzuci IllegalArgumentException.

D3. Jeśli zdecydujesz się na dbać ręcznie o swoje identyfikatory (np. za pomocą uuid), a następnie merge operacja wywoła kolejne zapytania SELECT w celu wyszukania istniejących encji o tym ID, podczas gdy persist może nie potrzebować tych zapytań.

D4. Są przypadki, gdy po prostu nie ufasz kodowi, który wywołuje twój kod, i aby upewnić się, że żadne dane nie są aktualizowane, ale raczej są wstawiane, musisz użyć persist.

 15
Author: Andrei I,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-02 14:13:56

Otrzymywałem leniwe ładowanie WYJĄTKÓW na moim obiekcie, ponieważ próbowałem uzyskać dostęp do leniwej załadowanej kolekcji, która była w sesji.

To, co bym zrobił, to osobne żądanie, odzyskanie encji z sesji, a następnie próba uzyskania dostępu do kolekcji na mojej stronie jsp, co było problematyczne.

Aby to złagodzić, zaktualizowałem ten sam element w moim kontrolerze i przekazałem go do mojego jsp, chociaż wyobrażam sobie, że po ponownym zapisaniu w sesji będzie on również dostępny, chociaż SessionScope i nie rzucać a LazyLoadingException, modyfikacja przykładu 2:

Dla mnie działa:

// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"

//access e from jsp and it will work dandy!!
 8
Author: logixplayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-21 11:01:11

Przechodząc przez odpowiedzi brakuje pewnych szczegółów dotyczących "kaskady" i generowania id. Zobacz pytanie

Warto również wspomnieć, że do scalania i utrzymywania można mieć osobne adnotacje Cascade: Cascade.MERGE i Cascade.PERSIST, które będą traktowane zgodnie z zastosowaną metodą.

Spec jest twoim przyjacielem;)
 6
Author: Ioannis Deligiannis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Scenariusz X:

Table: Spitter (One) ,Table: Spittles (Many) (Spittles jest właścicielem relacji z FK:spitter_id)

Ten scenariusz skutkuje zapisaniem: Plujka i oba plujki jakby były własnością tego samego Plujka.

        Spitter spitter=new Spitter();  
    Spittle spittle3=new Spittle();     
    spitter.setUsername("George");
    spitter.setPassword("test1234");
    spittle3.setSpittle("I love java 2");       
    spittle3.setSpitter(spitter);               
    dao.addSpittle(spittle3); // <--persist     
    Spittle spittle=new Spittle();
    spittle.setSpittle("I love java");
    spittle.setSpitter(spitter);        
    dao.saveSpittle(spittle); //<-- merge!!

Scenariusz Y:

To uratuje Plujka, uratuje 2 plujki, ale nie będą odwoływać się do tego samego Plujka!

        Spitter spitter=new Spitter();  
    Spittle spittle3=new Spittle();     
    spitter.setUsername("George");
    spitter.setPassword("test1234");
    spittle3.setSpittle("I love java 2");       
    spittle3.setSpitter(spitter);               
    dao.save(spittle3); // <--merge!!       
    Spittle spittle=new Spittle();
    spittle.setSpittle("I love java");
    spittle.setSpitter(spitter);        
    dao.saveSpittle(spittle); //<-- merge!!
 5
Author: George Papatheodorou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-28 18:06:38

Znalazłem to Wyjaśnienie z dokumentów Hibernate, ponieważ zawierają one przypadek użycia:

Użycie i semantyka metody merge () wydaje się być mylące dla nowych użytkowników. Po pierwsze, dopóki nie próbujesz użyć stanu obiektu załadowanego w jednym Menedżerze encji w innym Menedżerze encji, nie powinieneś w ogóle używać merge () . Niektóre całe aplikacje nigdy nie będą używać tej metody.

Zwykle merge() jest używane w następującym scenariuszu:

  • aplikacja ładuje obiekt w pierwszym Menedżerze encji
  • obiekt jest przekazywany do warstwy prezentacji
  • niektóre modyfikacje są wprowadzane do obiektu
  • obiekt jest przekazywany z powrotem do warstwy logiki biznesowej
  • aplikacja kontynuuje te modyfikacje, wywołując merge () w drugim Menedżerze encji

Oto dokładny semantyczny merge ():

  • jeśli istnieje instancja zarządzana z tym samym identyfikator aktualnie skojarzony z kontekstem persistence, kopiuje stan danego obiektu na instancję zarządzaną
  • jeśli żadna instancja zarządzana nie jest obecnie powiązana z kontekstem trwałości, spróbuj załadować ją z bazy danych lub utwórz nową instancję zarządzaną
  • zwracana jest instancja zarządzana
  • dana instancja nie wiąże się z kontekstem trwałości, pozostaje oderwana i zwykle jest odrzucana

From: http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html

 5
Author: Ray Hulha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 16:28:54

JPA jest bezsprzecznie wielkim uproszczeniem w dziedzinie przedsiębiorczości aplikacje zbudowane na platformie Java. Jako deweloper, który musiał uporać się z zawiłościami starego bytu w J2EE widzę włączenie JPA do specyfikacji Java EE jako duży skok naprzód. Jednak zagłębiając się głębiej w szczegóły JPA znajduję rzeczy, które nie są takie łatwe. W tym artykule zajmuję się porównaniem metody merge i persist EntityManager, których nakładanie się zachowanie może powodować zamieszanie nie tylko dla nowicjusza. Ponadto zaproponuj uogólnienie, które postrzega obie metody jako szczególne przypadki bardziej ogólna metoda łączenia.

Persisting entities

W przeciwieństwie do metody merge metoda persist jest dość prosta i intuicyjna. Najczęstszy scenariusz użycia metody persist można podsumować następująco:

" nowo utworzona instancja klasy encji jest przekazywana do persist metoda. Po powrocie tej metody obiekt jest zarządzany i planowany do wstawienia do bazy danych. Może się to zdarzyć przed zatwierdzeniem transakcji lub podczas wywołania metody flush. Jeżeli jednostka odwołuje się do innej jednostki poprzez relację oznaczoną strategią PERSIST cascade, procedura ta jest również stosowana do niej."

Tutaj wpisz opis obrazka

Specyfikacja idzie bardziej w szczegóły, jednak zapamiętywanie ich nie jest kluczowe, ponieważ te szczegóły obejmują mniej lub bardziej egzotyczne tylko sytuacje.

Scalanie jednostek

W porównaniu do persist, opis zachowania połączenia nie jest taki prosty. Nie ma scenariusza głównego, jak to ma miejsce w przypadku persist, a programista musi zapamiętać wszystkie scenariusze, aby napisać poprawny kod. Wydaje mi się, że projektanci JPA chcieli mieć jakąś metodę, której głównym problemem byłoby obchodzenie się z wolnymi podmiotami (jako przeciwieństwo metody persist, która dotyczy nowo utworzonych podmiotów przede wszystkim.) Głównym zadaniem metody merge jest przeniesienie stanu z jednostki niezarządzanej (przekazywanej jako argument) do jej zarządzanego odpowiednika w kontekście persistence. Zadanie to jednak dzieli się dalej na kilka scenariuszy, które pogarszają zrozumiałość ogólnego zachowania metody.

Zamiast powtarzać akapity ze specyfikacji JPA przygotowałem schemat, który schematycznie przedstawia zachowanie merge "metoda": {]}

Tutaj wpisz opis obrazka

Kiedy powinienem używać persist i kiedy merge?

Persist

  • chcesz, aby metoda zawsze tworzyła nowy element i nigdy go nie aktualizowała. W przeciwnym razie metoda rzuca wyjątek w wyniku naruszenia wyjątkowości klucza głównego.
  • procesy wsadowe, obsługujące jednostki w sposób Stanowy (patrz wzorzec bramy).
  • wydajność optymalizacja

Merge

  • chcesz, aby metoda wstawiała lub aktualizowała obiekt w bazie danych.
  • W 2007 roku firma została założona przez firmę Microsoft, która od 2007 roku zajmuje się dystrybucją i dystrybucją danych.]}
  • chcesz wstawić nowy obiekt, który może mieć odniesienie do innego obiektu, który może, ale nie może być jeszcze utworzony (relacja musi być oznaczona jako MERGE). Na przykład wstawianie nowego zdjęcia z odniesieniem do nowego lub wcześniejszego album.
 5
Author: Amit Gujarathi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 12:36:08

Być może przyszedłeś tutaj po poradę, kiedy używać persist i kiedy używać merge. Myślę, że to zależy od sytuacji: jak prawdopodobne jest, że trzeba utworzyć nowy rekord i jak trudno jest odzyskać utrzymane dane.

Załóżmy, że możesz użyć naturalnego klucza / identyfikatora.

  • Dane muszą być przechowywane, ale raz na jakiś czas istnieje rekord i wymagana jest aktualizacja. W tym przypadku można spróbować persist i jeśli rzuca EntityExistsException, wyszukujesz go i łączysz DANE:

    Try { entityManager.persist (entity)}

    Catch (wyjątek EntityExistsException) {/*retrieve and merge*/}

  • Dane przechowywane muszą zostać zaktualizowane, ale raz na jakiś czas nie ma jeszcze rekordu dla tych danych. W tym przypadku poszukujesz go i wykonujesz persist, jeśli brakuje encji:

    Entity = entityManager.find (klucz);

    If (entity = = null) {entityManager.persist(Jednostka); }

    Else {/*merge */}

Jeśli nie masz naturalnego klucza/identyfikatora, będziesz miał trudniejszy czas, aby dowiedzieć się, czy podmiot istnieje, czy nie, lub jak go wyszukać.

Z połączeniami można też poradzić sobie na dwa sposoby:

  1. jeśli zmiany są zwykle niewielkie, zastosuj je do zarządzanego podmiotu.
  2. jeśli zmiany są powszechne, skopiuj ID z trwałej jednostki, a także niezmienione dane. Następnie wywołaj metodę EntityManager:: merge (), aby zastąpić starą treść.
 1
Author: Peter Willems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-06 20:15:10

Persist (entity) powinien być używany z całkowicie nowymi encjami, aby dodać je do DB (jeśli encja już istnieje w DB, to Entity Existsexception throw).

Należy użyć Merge(entity), aby przywrócić entity do kontekstu persistence, jeśli encja została odłączona i zmieniona.

Prawdopodobnie persist generuje polecenie INSERT sql i Merge UPDATE SQL (ale nie jestem pewien).

 0
Author: Krystian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-04 12:38:37

Kolejna obserwacja:

merge() będzie dbał o automatycznie wygenerowany identyfikator (testowany na IDENTITY i SEQUENCE) tylko wtedy, gdy rekord o takim identyfikatorze już istnieje w Twojej tabeli. W takim przypadku merge() spróbuje zaktualizować rekord. Jeśli jednak nie ma identyfikatora lub nie pasuje do żadnego istniejącego rekordu, merge() całkowicie go zignoruje i poprosi db o przydzielenie nowego. Czasami jest to źródło wielu błędów. Nie używaj merge(), aby wymusić id dla nowego rekordu.

persist() z drugiej strony będzie nigdy nie pozwoliłem ci go nawet zidentyfikować. Natychmiast się nie powiedzie. W moim przypadku jest to:

Spowodowane przez: org.hibernacja.PersistentObjectException: detected entity passed to persist

Hibernate-jpa javadoc ma podpowiedź:

Rzuty : javax.wytrwałość.EntityExistsException-jeżeli podmiot już istnieje. (Jeżeli jednostka już istnieje, to EntityExistsException może zostać wyrzucony, gdy operacja persist jest wywołany, lub podmiot lub innym uporczywym może być rzucany w czasie koloru lub commit.)

 0
Author: yuranos87,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 15:06:49