Jaka jest różnica między sesją.persist () i session.save () w Hibernate?

Czy ktoś może mi powiedzieć jaka jest zaleta persist() vs save() w Hibernate?

Author: Giorgi Tsiklauri, 2011-05-02

10 answers

From this forum post

persist() jest dobrze zdefiniowany. To sprawia, że przejściowa instancja trwała. Nie gwarantuje jednak, że wartość identyfikatora zostanie przypisana do trwała instancja natychmiast, zadanie może nastąpić w momencie czas. Spec tego nie mówi, co czy mam problem z persist().

persist() gwarantuje również, że będzie nie wykonuje instrukcji INSERT, jeśli jest wywoływany poza transakcją granice. Jest to przydatne w długotrwałe rozmowy z Rozszerzony kontekst sesji/trwałości.

Wymagana jest metoda podobna do persist().

save() nie gwarantuje tego samego, to zwraca identyfikator, a jeśli INSERT musi zostać wykonany, aby uzyskać identyfikator (np. generator "tożsamości", nie "sekwencja"), ta wstawka dzieje się natychmiast, bez względu na to, czy jesteś w ramach transakcji lub poza nią. To nie jest dobre na dłuższą metę rozmowa z rozszerzonym Kontekst sesji/trwałości.

 158
Author: Bala R,
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-09-22 18:27:16

Zrobiłem dobre badania na save () vs. persist (), w tym uruchomiłem go na mojej lokalnej maszynie kilka razy. Wszystkie poprzednie wyjaśnienia są mylące i błędne. Porównuję metody save() i persist() poniżej po dokładnych badaniach.

Save()

  1. zwraca wygenerowany identyfikator po zapisaniu. Jego typ powrotu to Serializable;
  2. zapisuje zmiany w bazie danych poza transakcją;
  3. przypisuje wygenerowany identyfikator do podmiotu, którym jesteś persisting;
  4. session.save() dla odłączonego obiektu utworzy nowy wiersz w tabeli.

Persist()

  1. nie zwraca wygenerowanego identyfikatora po zapisaniu. Jego typ powrotu to void;
  2. nie zapisuje zmian w bazie danych poza transakcją;
  3. przypisuje wygenerowany identyfikator do podmiotu, który się utrzymuje;
  4. session.persist() dla odłączonego obiektu rzuci PersistentObjectException, ponieważ nie jest to dozwolone.

Wszystkie są wypróbowane / przetestowane na Hibernate v4.0.1.

 75
Author: Zeus,
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
2020-09-01 23:07:39

Zrobiłem kilka prób, aby zarejestrować różnicę między save() i persist().

Wygląda na to, że obie te metody zachowują się tak samo, gdy mają do czynienia z podmiotem przejściowym, ale różnią się, gdy mają do czynienia z podmiotem odłączonym.

W poniższym przykładzie weźmy EmployeeVehicle jako jednostkę z PK jako vehicleId, która jest wygenerowaną wartością i vehicleName jako jedną z jej właściwości.

Przykład 1: radzenie sobie z obiektami przejściowymi

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Wynik:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Uwaga wynik jest taki sam gdy otrzymasz już istniejący obiekt i zapisz go

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

Powtórz to samo używając persist(entity) i spowoduje to samo z nowym Id ( powiedzmy 37 , honda);

Przykład 2: radzenie sobie z odłączonym obiektem

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

Wynik: możesz się spodziewać, że pojazd o id: 36 uzyskany w poprzedniej sesji zostanie zaktualizowany o nazwę "Toyota". Ale dzieje się tak, że nowa jednostka jest zapisywana w DB z nowym identyfikatorem wygenerowanym dla I nazwą jako "Toyota"

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

Using persist to persist detergent entity

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

Wynik:

Exception being thrown : detached entity passed to persist

Dlatego zawsze lepiej jest użyć Persist() zamiast Save (), ponieważ save musi być ostrożnie używany podczas obsługi obiektu przejściowego .

Ważna uwaga : w powyższym przykładzie wartość pk jednostki vehicle jest wygenerowaną wartością , więc podczas używania save() do persist odłączonej jednostki , hibernate generuje nowy identyfikator do persist . Jeśli jednak pk nie jest wygenerowaną wartością, to spowoduje to wyjątek z kluczem naruszone.

 25
Author: Deivanayagam Senthil,
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-12-15 18:06:06

To pytanie zawiera kilka dobrych odpowiedzi na temat różnych metod trwałości W Hibernate. Aby odpowiedzieć bezpośrednio na twoje pytanie, za pomocą save() instrukcja insert jest wykonywana natychmiast, niezależnie od stanu transakcji. Zwraca wstawiony klucz, więc możesz zrobić coś takiego:

long newKey = session.save(myObj);

Więc użyj save (), jeśli musisz natychmiast przypisać identyfikator do trwałej instancji.

Z persist (), instrukcja insert jest wykonywana w transakcji, niekoniecznie natychmiast. W większości przypadków jest to preferowane.

Użyj persist (), jeśli nie potrzebujesz insert, aby transakcja przebiegała poza sekwencją i nie potrzebujesz zwracanego klucza.

 14
Author: CFL_Jeff,
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:54:58

Save () - jak sugeruje nazwa metody, hibernate save () może być użyte do zapisania encji do bazy danych. Możemy wywołać tę metodę poza transakcją. Jeśli użyjemy tego bez transakcji i mamy kaskadowe między encjami, wtedy tylko element podstawowy zostanie zapisany, chyba że spłukamy sesję.

Persist()-Hibernate persist jest podobny do save (z transakcją) i dodaje obiekt entity do trwałego kontekstu, więc wszelkie dalsze zmiany są śledzone. Jeśli Właściwości obiektu są zmieniona przed zatwierdzeniem transakcji lub usunięciem sesji, zostanie również zapisana do bazy danych. Ponadto, możemy użyć metody persist() tylko w granicach transakcji, więc jest ona bezpieczna i zajmuje się kaskadowymi obiektami. Na koniec, persist nie zwraca niczego, więc musimy użyć obiektu persisted, aby uzyskać wygenerowaną wartość identyfikatora.

 6
Author: Rohit Goyal,
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-04-20 20:16:37

Oto różnice, które mogą pomóc ci zrozumieć zalety metod persist i save:

  • pierwszą różnicą pomiędzy Save i persist jest ich typ powrotu. Na return type of persist method is void while return type of save
    metoda jest obiektem Serializowalnym.
  • Metoda persist () nie gwarantuje, że wartość identyfikatora będzie być natychmiast przypisane do stanu trwałego, przypisanie może dzieje się w czasie spłukiwania.

  • Na metoda persist () nie wykona zapytania insert, jeśli zostanie wywołana poza granicami transakcji. While, metoda save() zwraca identyfikatora tak, że zapytanie Wstaw jest wykonywane natychmiast, aby uzyskać identyfikator, bez względu na to, czy znajduje się wewnątrz, czy na zewnątrz transakcja.

  • Metoda persist jest wywoływana poza granicami transakcji, jest przydatne w długotrwałych rozmowach z rozszerzoną sesją kontekst. Z drugiej strony metoda save nie jest dobra w long-running rozmowa z rozszerzonym kontekstem sesji.

  • Piąta różnica między metodą save i persist w Hibernate: persist jest wspierany przez JPA, podczas gdy save jest wspierany tylko przez Hibernacja.

Możesz zobaczyć pełny działający przykład z post różnica między metodą save i persist w Hibernate

 6
Author: David Pham,
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
2019-11-11 09:09:49

Oto różnica:

  1. Zapisz:

    1. zwróci id / identyfikator, gdy obiekt zostanie zapisany do bazy danych.
    2. zapisze również, gdy obiekt spróbuje zrobić to samo, otwierając nową sesję po jej odłączeniu.
    1. zwróci void, gdy obiekt zostanie zapisany do bazy danych.
    2. wyrzuci PersistentObjectException, gdy spróbujesz zapisać odłączony obiekt przez nowy sesja.
 5
Author: Mohammed Amen,
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-01-28 15:48:46

Podstawowa zasada mówi, że:

Dla podmiotów o wygenerowanym identyfikatorze:

Save (): zwraca identyfikator obiektu natychmiast, oprócz uczynienia obiektu trwałym. Tak więc zapytanie Wstaw jest wywoływane natychmiast.

Persist() : zwraca trwały obiekt. Nie ma żadnego przymusu natychmiastowego zwracania identyfikatora, więc nie gwarantuje, że insert zostanie natychmiast wywołany. Może odpalić wkładkę natychmiast, ale nie jest to gwarantowane. W niektórych przypadki, zapytanie może być wywołane natychmiast, podczas gdy w innych może być wywołane w czasie flush sesji.

Dla podmiotów z przypisanym identyfikatorem:

Save (): natychmiast zwraca identyfikator encji. Ponieważ identyfikator jest już przypisany do encji przed wywołaniem save, insert nie jest wywoływany natychmiast. Jest on uruchamiany w czasie sesji flush.

Persist() : tak samo jak save. Wystrzeliwuje również wkładkę w czasie spłukiwania.

Załóżmy, że mamy byt, który używa wygenerowanego identyfikator w następujący sposób:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

Save ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

Persist ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

Teraz Załóżmy, że mamy ten sam encja zdefiniowany w następujący sposób bez pola id generującego adnotację, tzn. ID zostanie przypisane ręcznie.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

Dla save ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

For persist ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

Powyższe przypadki były prawdziwe, gdy save lub persist zostały wywołane z poziomu transakcji.

Pozostałe punkty różnicy między save i persist to :

  1. Save () może być wywołane poza transakcją. Jeżeli zastosowany jest przypisany identyfikator, to ponieważ id jest już dostępne, więc żadne zapytanie insert nie jest natychmiast wywołane. Zapytanie jest wywoływane tylko wtedy, gdy sesja jest spłukana.

  2. Jeżeli użyto wygenerowanego identyfikatora , wtedy ponieważ id musi zostać wygenerowane, insert jest natychmiast wywołany. Ale to tylko ratuje pierwotną istotę. Jeśli encja ma kaskadowe encje, nie będą one zapisywane w db w tym momencie. Będą zbawieni kiedy sesja jest spłukana.

  3. Jeśli persist () znajduje się poza transakcją, to insert jest wywoływany tylko wtedy, gdy sesja jest spłukana bez względu na rodzaj identyfikatora (wygenerowanego lub przypisanego).

  4. Jeśli save jest wywoływany nad trwałym obiektem, To encja jest zapisywana za pomocą zapytania update.

 5
Author: Gaurav Kumar,
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
2019-10-16 13:24:02

Właściwie, różnica między metodami hibernate save() i persist() zależy od klasy generatora, której używamy.
Jeśli przypisana jest nasza klasa generatora, to nie ma różnicy między metodami save() i persist (). Ponieważ generator "przypisany" oznacza, jako programista musimy podać podstawową wartość klucza, aby zapisać w bazie danych w prawo [ mam nadzieję, że znasz tę koncepcję generatorów ] W przypadku innej niż przypisana klasy generatora, Załóżmy, że nasza klasa generatora to Increment oznacza sam hibernate przypisze wartość ID klucza podstawowego do bazy danych w prawo [poza przypisanym generatorem, hibernate służy tylko do dbania o zapamiętanie wartości ID klucza podstawowego], więc w tym przypadku, jeśli wywołamy metodę save () lub persist (), to normalnie wstawi rekord do bazy danych.
Ale tutaj chodzi o to, że metoda save() może zwrócić wartość ID klucza głównego, która jest generowana przez hibernate i możemy ją zobaczyć przez
Długie s = sesja.save (k);
W tym samym przypadku persist () nigdy nie będzie zwróć klientowi dowolną wartość, zwracając typ void.
persist() gwarantuje również, że nie wykona instrukcji INSERT, jeśli zostanie wywołana poza granicami transakcji.
podczas gdy w save () INSERT dzieje się natychmiast, bez względu na to, czy jesteś wewnątrz czy poza transakcją.

 2
Author: Hari Krishna,
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
2019-12-27 11:11:55

Całkowicie odpowiedział na podstawie typu "generator" w ID podczas przechowywania dowolnego podmiotu. Jeśli wartość dla generatora jest "przypisana", co oznacza, że podajesz ID. Następnie nie powoduje różnic w hibernate dla save lub persist. Możesz wybrać dowolną metodę. Jeśli wartość nie jest "przypisana" i używasz save (), to otrzymasz ID jako zwrot z operacji save ().

Kolejnym sprawdzeniem jest, czy wykonujesz operację poza limitem transakcji, czy nie. Ponieważ persist () należy do JPA while save () dla hibernate. Tak więc użycie persist () poza granicami transakcji nie pozwoli na to i wyrzuci wyjątek związany z persistant. podczas gdy z save () nie ma takiego ograniczenia i można przejść z transakcją DB poprzez save () poza limitem transakcji.

 1
Author: Neeraj,
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-07-25 11:48:16