Antworten:
persist()
ist gut definiert. Dadurch wird eine vorübergehende Instanz dauerhaft. Es kann jedoch nicht garantiert werden, dass der Bezeichnerwert sofort der persistenten Instanz zugewiesen wird. Die Zuweisung kann zum Zeitpunkt des Löschvorgangs erfolgen. Die Spezifikation sagt das nicht, was das Problem ist, mit dem ich habepersist()
.
persist()
garantiert auch, dass eine INSERT-Anweisung nicht ausgeführt wird, wenn sie außerhalb der Transaktionsgrenzen aufgerufen wird. Dies ist nützlich bei lang laufenden Gesprächen mit einem erweiterten Sitzungs- / Persistenzkontext.Eine Methode wie
persist()
ist erforderlich.
save()
garantiert nicht dasselbe, es gibt einen Bezeichner zurück, und wenn ein INSERT ausgeführt werden muss, um den Bezeichner zu erhalten (z. B. "Identitätsgenerator", nicht "Sequenz"), geschieht dieses EINFÜGEN sofort, unabhängig davon, ob Sie sich innerhalb oder außerhalb von befinden eine Transaktion. Dies ist in einem langjährigen Gespräch mit einem erweiterten Sitzungs- / Persistenzkontext nicht gut.
Ich habe gut über save () vs persist () recherchiert und es mehrmals auf meinem lokalen Computer ausgeführt. Alle vorherigen Erklärungen sind verwirrend und nicht korrekt. Ich habe das Speichern () und das Beharren () unten nach einer gründlichen Recherche verglichen.
Save()
Serializable
Rückgabetyp.Persist()
generated id
der Entität zu, die Sie beibehaltensession.persist()
denn ein abgetrenntes Objekt wird werfen, PersistentObjectException
da es nicht erlaubt ist.All dies hat sich bewährt Hibernate v4.0.1
.
Save()
?
Ich habe einige Mock-Tests durchgeführt, um den Unterschied zwischen save()
und aufzuzeichnen persist()
.
Klingt so, als ob sich beide Methoden beim Umgang mit transienter Entität gleich verhalten, sich jedoch beim Umgang mit losgelöster Entität unterscheiden.
Nehmen Sie für das folgende Beispiel EmployeeVehicle als Entität mit PK als vehicleId
generiertem Wert und vehicleName
als eine seiner Eigenschaften.
Beispiel 1: Umgang mit transienten Objekten
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();
Ergebnis:
select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)
Beachten Sie, dass das Ergebnis dasselbe ist, wenn Sie ein bereits bestehendes Objekt erhalten und speichern
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity); -------> **instead of session.update(entity);**
// session.persist(entity);
Wiederholen Sie das gleiche mit persist(entity)
und erhalten Sie das gleiche mit neuer ID (sagen wir 37, honda);
Beispiel 2: Umgang mit abgelösten Objekten
// 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();
Ergebnis: Möglicherweise erwarten Sie, dass das in der vorherigen Sitzung erhaltene Fahrzeug mit der ID: 36 mit dem Namen "Toyota" aktualisiert wird. Was jedoch passiert, ist, dass eine neue Entität in der Datenbank mit einer neuen ID und einem Namen als "Toyota" gespeichert wird.
select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)
Verwenden von persist, um eine getrennte Entität beizubehalten
// (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();
Ergebnis:
Exception being thrown : detached entity passed to persist
Daher ist es immer besser, Persist () anstelle von Save () zu verwenden, da save beim Umgang mit transienten Objekten sorgfältig verwendet werden muss.
Wichtiger Hinweis: Im obigen Beispiel ist der pk der Fahrzeugentität ein generierter Wert. Wenn Sie also save () verwenden, um eine getrennte Entität beizubehalten, generiert der Ruhezustand eine neue ID, die beibehalten werden soll. Wenn dieses pk jedoch kein generierter Wert ist, führt dies zu einer Ausnahme, bei der angegeben wird, dass der Schlüssel verletzt wurde.
Diese Frage enthält einige gute Antworten zu verschiedenen Persistenzmethoden im Ruhezustand. Um Ihre Frage direkt zu beantworten, wird mit save () die insert-Anweisung unabhängig vom Transaktionsstatus sofort ausgeführt. Es gibt den eingefügten Schlüssel zurück, sodass Sie Folgendes tun können:
long newKey = session.save(myObj);
Verwenden Sie also save (), wenn Sie eine Kennung benötigen, die der persistenten Instanz sofort zugewiesen wird.
Mit persist () wird die insert-Anweisung in einer Transaktion nicht unbedingt sofort ausgeführt. Dies ist in den meisten Fällen vorzuziehen.
Verwenden Sie persist (), wenn die Einfügung nicht außerhalb der Reihenfolge der Transaktion erfolgen soll und der eingefügte Schlüssel nicht zurückgegeben werden muss.
Hier sind die Unterschiede, die Ihnen helfen können, die Vorteile von Methoden zum Speichern und Speichern zu verstehen:
Die persist () -Methode garantiert nicht, dass der Bezeichnerwert sofort dem persistenten Status zugewiesen wird. Die Zuweisung kann zum Zeitpunkt des Löschvorgangs erfolgen.
Die persist () -Methode führt keine Einfügeabfrage aus, wenn sie außerhalb der Transaktionsgrenzen aufgerufen wird. Währenddessen gibt die save () -Methode einen Bezeichner zurück, sodass eine Einfügeabfrage sofort ausgeführt wird, um den Bezeichner abzurufen, unabhängig davon, ob er sich innerhalb oder außerhalb einer Transaktion befindet.
Die persist-Methode wird außerhalb von Transaktionsgrenzen aufgerufen. Sie ist nützlich bei lang laufenden Konversationen mit einem erweiterten Sitzungskontext. Andererseits ist die Speichermethode in einer langen Konversation mit einem erweiterten Sitzungskontext nicht gut.
Fünfter Unterschied zwischen der Save- und der Persist-Methode im Ruhezustand: Persist wird von JPA unterstützt, während Save nur von Hibernate unterstützt wird.
Das vollständige Arbeitsbeispiel finden Sie im Beitrag Unterschied zwischen Speichern und Behalten im Ruhezustand
save () - Wie der Methodenname andeutet, kann save () im Ruhezustand verwendet werden, um die Entität in der Datenbank zu speichern. Wir können diese Methode außerhalb einer Transaktion aufrufen. Wenn wir dies ohne Transaktion verwenden und zwischen Entitäten kaskadieren, wird nur die primäre Entität gespeichert, es sei denn, wir leeren die Sitzung.
persist () - Persist im Ruhezustand ähnelt dem Speichern (mit Transaktion) und fügt das Entitätsobjekt dem persistenten Kontext hinzu, sodass weitere Änderungen nachverfolgt werden. Wenn die Objekteigenschaften geändert werden, bevor die Transaktion festgeschrieben oder die Sitzung geleert wird, wird sie auch in der Datenbank gespeichert. Außerdem können wir die persist () -Methode nur innerhalb der Grenzen einer Transaktion verwenden, sodass sie sicher ist und sich um alle kaskadierten Objekte kümmert. Schließlich gibt persist nichts zurück, sodass wir das persistierte Objekt verwenden müssen, um den generierten Bezeichnerwert zu erhalten.
Hier ist der Unterschied:
sparen:
Fortdauern:
Grundregel besagt, dass:
Für Entitäten mit generierter Kennung:
save (): Gibt die Kennung einer Entität sofort zurück und macht das Objekt dauerhaft. Eine Insert-Abfrage wird also sofort ausgelöst.
persist (): Gibt das persistente Objekt zurück. Es besteht kein Zwang, die Kennung sofort zurückzugeben, so dass nicht garantiert werden kann, dass der Einsatz sofort ausgelöst wird. Es kann sein, dass ein Einsatz sofort ausgelöst wird, dies ist jedoch nicht garantiert. In einigen Fällen wird die Abfrage möglicherweise sofort ausgelöst, während sie in anderen Fällen zum Zeitpunkt der Sitzungsspülung ausgelöst wird.
Für Entitäten mit zugewiesener Kennung:
save (): Gibt sofort die Kennung einer Entität zurück. Da der Bezeichner bereits vor dem Aufruf von save der Entität zugewiesen wurde, wird insert nicht sofort ausgelöst. Es wird zur Sitzungsspülzeit ausgelöst.
persist (): wie save. Es feuert auch Einsatz zum Spülzeitpunkt.
Angenommen, wir haben eine Entität, die einen generierten Bezeichner wie folgt verwendet:
@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;
}
}
sparen() :
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();
fortdauern() :
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();
Angenommen, wir haben dieselbe Entität wie folgt definiert, ohne dass das ID-Feld eine Annotation generiert hat, dh die ID wird manuell zugewiesen.
@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;
}
}
für 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();
für 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();
Die oben genannten Fälle waren zutreffend, als das Speichern oder Fortbestehen innerhalb einer Transaktion aufgerufen wurde.
Die anderen Unterschiede zwischen Speichern und Fortbestehen sind:
save () kann außerhalb einer Transaktion aufgerufen werden. Wenn die zugewiesene Kennung verwendet wird, wird die ID nicht sofort ausgelöst, da die ID bereits verfügbar ist. Die Abfrage wird nur ausgelöst, wenn die Sitzung geleert wird.
Wenn die generierte Kennung verwendet wird, wird die Einfügung sofort ausgelöst, da die ID generiert werden muss. Es wird jedoch nur die primäre Entität gespeichert. Wenn die Entität einige kaskadierte Entitäten hat, werden diese zu diesem Zeitpunkt nicht in db gespeichert. Sie werden gespeichert, wenn die Sitzung geleert wird.
Befindet sich persist () außerhalb einer Transaktion, wird insert nur ausgelöst, wenn die Sitzung gelöscht wird, unabhängig davon, welche Art von Kennung (generiert oder zugewiesen) verwendet wird.
Wenn save über ein persistentes Objekt aufgerufen wird, wird die Entität mithilfe der Aktualisierungsabfrage gespeichert.
Tatsächlich hängt der Unterschied zwischen den Methoden save () und persist () im Ruhezustand von der von uns verwendeten Generatorklasse ab.
Wenn unsere Generatorklasse zugewiesen ist, gibt es keinen Unterschied zwischen den Methoden save () und persist (). Da Generator 'zugewiesen' bedeutet, müssen wir als Programmierer den Primärschlüsselwert angeben, der in der Datenbank gespeichert werden soll. [Hoffe, Sie kennen dieses Generatorkonzept] Nehmen Sie bei einer anderen als der zugewiesenen Generatorklasse an, ob unser Generatorklassenname Inkrement bedeutet Der Ruhezustand selbst weist der Datenbank den Primärschlüssel-ID-Wert zu [außer dem zugewiesenen Generator wird der Ruhezustand nur verwendet, um den Primärschlüssel-ID-Wert zu speichern]. In diesem Fall also, wenn wir die Methode save () oder persist () aufrufen Der Datensatz wird normal in die Datenbank eingefügt.
Hier kann die save () -Methode den Primärschlüssel-ID-Wert zurückgeben, der im Ruhezustand generiert wird, und wir können ihn durch
long s = session.save (k) sehen.
In diesem Fall gibt persist () dem Client niemals einen Wert zurück, Rückgabetyp void.
persist () garantiert auch, dass eine INSERT-Anweisung nicht ausgeführt wird, wenn sie außerhalb der Transaktionsgrenzen aufgerufen wird.
Während in save () INSERT sofort ausgeführt wird, unabhängig davon, ob Sie sich innerhalb oder außerhalb einer Transaktion befinden.
Es wurde vollständig auf der Basis des ID-Typs "Generator" geantwortet, während eine Entität gespeichert wurde. Wenn der Wert für den Generator "zugewiesen" ist, bedeutet dies, dass Sie die ID angeben. Dann macht es keinen Unterschied im Ruhezustand zum Speichern oder Fortbestehen. Sie können mit jeder gewünschten Methode gehen. Wenn der Wert nicht "zugewiesen" ist und Sie save () verwenden, erhalten Sie eine ID als Rückgabe von der Operation save ().
Eine weitere Überprüfung besteht darin, ob Sie den Vorgang außerhalb des Transaktionslimits ausführen oder nicht. Weil persist () zu JPA gehört, während save () für den Ruhezustand ist. Wenn Sie also persist () außerhalb der Transaktionsgrenzen verwenden, ist dies nicht möglich und es werden Ausnahmen in Bezug auf persistant ausgelöst. während mit save () keine solche Einschränkung besteht und man mit DB-Transaktion über save () außerhalb des Transaktionslimits gehen kann.