Odpowiedzi:
persist()
jest dobrze zdefiniowany. Sprawia, że przejściowe wystąpienie jest trwałe. Jednak nie gwarantuje, że wartość identyfikatora zostanie natychmiast przypisana do trwałego wystąpienia, przypisanie może nastąpić w czasie opróżniania. Specyfikacja tego nie mówi, z czym mam problempersist()
.
persist()
gwarantuje również, że nie wykona instrukcji INSERT, jeśli zostanie wywołana poza granicami transakcji. Jest to przydatne w długotrwałych konwersacjach z rozszerzonym kontekstem sesji / trwałości.Taka metoda
persist()
jest wymagana.
save()
nie gwarantuje tego samego, zwraca identyfikator, a jeśli w celu uzyskania identyfikatora ma zostać wykonany INSERT (np. generator „tożsamości”, a nie „sekwencja”), to INSERT następuje natychmiast, bez względu na to, czy jesteś w środku, czy na zewnątrz transakcja. To nie jest dobre w długotrwałej konwersacji z rozszerzonym kontekstem sesji / trwałości.
Zrobiłem dobre badania dotyczące metody save () vs persist (), w tym kilka razy uruchamiając ją na moim komputerze lokalnym. Wszystkie poprzednie wyjaśnienia są mylące i nie są poprawne. Po dokładnym zbadaniu porównałem opcje save () i persist ()).
Save()
Serializable
typ zwrotu.Persist()
generated id
podmiotowi, który utrwalaszsession.persist()
dla odłączonego obiektu będzie rzucać, PersistentObjectException
ponieważ jest to niedozwolone.Wszystkie te są wypróbowane / przetestowane Hibernate v4.0.1
.
Save()
?
Zrobiłem kilka próbnych testów, aby zarejestrować różnicę między save()
i persist()
.
Wygląda na to, że obie te metody zachowują się tak samo, gdy mamy do czynienia z jednostką przejściową, ale różnią się w przypadku jednostki odłączonej.
W poniższym przykładzie weź EmployeeVehicle jako jednostkę z PK jako vehicleId
wygenerowaną wartością i vehicleName
jedną z jej właściwości.
Przykład 1: Radzenie sobie z przejściowym obiektem
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)
Zwróć uwagę, że wynik jest taki sam, gdy otrzymasz już utrwalony obiekt i zapiszesz 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życie 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 oczekiwać, że pojazd o identyfikatorze: 36 otrzymany w poprzedniej sesji zostanie zaktualizowany o nazwę „Toyota”. Ale dzieje się tak, że w bazie danych zapisywana jest nowa jednostka z nowym identyfikatorem wygenerowanym dla i nazwą „Toyota”
select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)
Używanie trwałego do utrwalania odłączonej jednostki
// (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żywać Persist () niż Save (), ponieważ save należy używać ostrożnie, gdy mamy do czynienia z obiektem Transient.
Ważna uwaga: W powyższym przykładzie pk jednostki pojazdu jest wygenerowaną wartością, więc gdy używasz save () do utrwalenia odłączonej jednostki, hibernacja generuje nowy identyfikator, aby zachować. Jeśli jednak ten pakiet nie jest wygenerowaną wartością, to skutkuje to wyjątkiem stwierdzającym, że klucz został naruszony.
Na to pytanie można znaleźć dobre odpowiedzi dotyczące różnych metod trwałości w Hibernate. Aby odpowiedzieć bezpośrednio na Twoje pytanie, za pomocą funkcji save () instrukcja wstawiania jest wykonywana natychmiastowo, niezależnie od stanu transakcji. Zwraca wstawiony klucz, więc możesz zrobić coś takiego:
long newKey = session.save(myObj);
Dlatego użyj metody save (), jeśli potrzebujesz natychmiastowego identyfikatora przypisanego do instancji trwałej.
W przypadku 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, aby wstawianie było wykonywane poza kolejnością z transakcją i nie potrzebujesz zwróconego wstawionego klucza.
Oto różnice, które mogą pomóc w zrozumieniu zalet metod utrwalania i zapisywania:
Metoda persist () nie gwarantuje, że wartość identyfikatora zostanie natychmiast przypisana do stanu trwałego, przypisanie może nastąpić w czasie opróżniania.
Metoda persist () nie wykona zapytania wstawiającego, jeśli zostanie wywołana poza granicami transakcji. Podczas gdy metoda save () zwraca identyfikator, więc zapytanie wstawiające jest wykonywane natychmiast w celu uzyskania identyfikatora, bez względu na to, czy znajduje się w transakcji, czy poza nią.
Metoda utrwalania jest wywoływana poza granicami transakcji, jest przydatna w długotrwałych konwersacjach z rozszerzonym kontekstem sesji. Z drugiej strony metoda save nie jest dobra w długotrwałej konwersacji z rozszerzonym kontekstem sesji.
Piąta różnica między metodą zapisywania i utrwalania w Hibernate: persist jest obsługiwana przez JPA, podczas gdy zapisywanie jest obsługiwane tylko przez Hibernate.
Możesz zobaczyć pełny przykład roboczy z postu Różnica między zapisem a utrwalaniem metody w Hibernacji
save () - Jak sugeruje nazwa metody, hibernacja save () może być użyta do zapisania jednostki do bazy danych. Możemy wywołać tę metodę poza transakcją. Jeśli używamy tego bez transakcji i mamy kaskadowanie między jednostkami, to tylko jednostka podstawowa zostanie zapisana, chyba że opróżnimy sesję.
persist () - Hibernate persist jest podobne do save (with transaction) i dodaje obiekt jednostki do trwałego kontekstu, więc wszelkie dalsze zmiany są śledzone. Jeśli właściwości obiektu zostaną zmienione przed zatwierdzeniem transakcji lub opróżnieniem sesji, zostanie on również zapisany w bazie danych. Ponadto możemy użyć metody persist () tylko w granicach transakcji, więc jest bezpieczna i dba o wszelkie obiekty kaskadowe. Wreszcie, persist nie zwraca niczego, więc musimy użyć utrwalonego obiektu, aby uzyskać wygenerowaną wartość identyfikatora.
Oto różnica:
zapisać:
Trwać:
Podstawowa zasada mówi, że:
Dla podmiotów z wygenerowanym identyfikatorem:
save (): Oprócz tego, że obiekt jest trwały, natychmiast zwraca identyfikator jednostki. Więc zapytanie wstawiające jest uruchamiane natychmiast.
persist (): zwraca trwały obiekt. Nie ma obowiązku natychmiastowego zwracania identyfikatora, więc nie gwarantuje, że insert zostanie natychmiast uruchomiony. Może natychmiast odpalić wkładkę, ale nie jest to gwarantowane. W niektórych przypadkach zapytanie może zostać uruchomione natychmiast, podczas gdy w innych może zostać uruchomione w czasie opróżniania sesji.
Dla podmiotów z przypisanym identyfikatorem:
save (): natychmiast zwraca identyfikator jednostki. Ponieważ identyfikator jest już przypisany do jednostki przed wywołaniem save, więc insert nie jest uruchamiany natychmiast. Jest uruchamiany w czasie sesji.
persist (): to samo co save. Wypala również wkładkę w czasie spłukiwania.
Załóżmy, że mamy jednostkę, która używa wygenerowanego identyfikatora 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;
}
}
zapisać() :
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();
przetrwać ():
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 tę samą jednostkę zdefiniowaną w następujący sposób, bez pola id, które wygenerowało adnotację, tj. 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;
}
}
za zaoszczędzenie ():
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 zapisywanie lub utrwalanie zostały wywołane z transakcji.
Inne punkty różnicy między zapisaniem a utrwalaniem to:
Funkcja save () może zostać wywołana poza transakcją. Jeśli używany jest przypisany identyfikator, to ponieważ identyfikator jest już dostępny, więc żadne zapytanie nie jest natychmiast uruchamiane. Zapytanie jest uruchamiane tylko po opróżnieniu sesji.
Jeśli używany jest wygenerowany identyfikator, to ponieważ id trzeba wygenerować, insert jest natychmiast uruchamiany. Ale zapisuje tylko pierwotną jednostkę. Jeśli jednostka ma kilka jednostek kaskadowych, nie zostaną one zapisane w bazie danych w tym momencie. Zostaną zapisane po opróżnieniu sesji.
Jeśli persist () znajduje się poza transakcją, to insert jest uruchamiany tylko wtedy, gdy sesja jest opróżniana, bez względu na rodzaj używanego identyfikatora (wygenerowany lub przypisany).
Jeśli funkcja save jest wywoływana przez trwały obiekt, jednostka jest zapisywana przy użyciu zapytania aktualizującego.
W rzeczywistości różnica między hibernacją metodami save () i persist () zależy od klasy generatora, którego używamy.
Ale tutaj chodzi o to, że metoda save () może zwrócić wartość identyfikatora klucza podstawowego, która jest generowana przez hibernację i możemy to zobaczyć przez
long s = session.save (k);
W tym samym przypadku persist () nigdy nie zwróci klientowi żadnej wartości, 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ś w transakcji, czy poza nią.
Jeśli przypisana jest nasza klasa generatora, nie ma różnicy między metodami save () i persist (). Ponieważ generator „przypisany” oznacza, jako programista musimy podać wartość klucza głównego do zapisania w bazie danych w prawo [Mam nadzieję, że znasz tę koncepcję generatorów] W przypadku innej niż przypisana klasa generatora, załóżmy, że nazwa naszej klasy generatora to Przyrost oznacza hibernacja sama przypisze wartość id klucza podstawowego do bazy danych w prawo [inny niż przypisany generator, hibernacja służy tylko do dbania o wartość identyfikatora klucza podstawowego zapamiętaj], więc w tym przypadku, jeśli wywołasz metodę save () lub persist (), to normalnie wstawi rekord do bazy danych.
Odpowiadał całkowicie na podstawie identyfikatora typu „generator” podczas przechowywania dowolnego podmiotu. Jeśli wartość dla generatora jest „przypisana”, co oznacza, że podajesz ID. Wtedy nie robi różnicy w hibernacji przy zapisywaniu lub utrwalaniu. Możesz wybrać dowolną metodę. Jeśli wartość nie jest „przypisana” i używasz funkcji save (), otrzymasz identyfikator jako zwrot z operacji save ().
Kolejnym sprawdzeniem jest to, czy wykonujesz operację poza limitem transakcji, czy nie. Ponieważ persist () należy do JPA, a save () na hibernację. Tak więc użycie persist () poza granicami transakcji nie pozwoli na to i zgłosi wyjątek związany z persistant. podczas gdy z save () nie ma takiego ograniczenia i można przejść z transakcją DB przez save () poza limit transakcji.