web-dev-qa-db-de.com

Was ist der Vorteil von persist () gegenüber save () im Ruhezustand?

Kann mir jemand sagen, was der Vorteil von persist() vs save() im Ruhezustand ist?

156
Antonio

Von dieser Forumsbeitrag

persist() ist gut definiert. Dadurch wird eine vorübergehende Instanz persistent. Es kann jedoch nicht garantiert werden, dass der Bezeichnerwert sofort der persistenten Instanz zugewiesen wird. Die Zuweisung kann zum Zeitpunkt des Flushs erfolgen. Die Spezifikation sagt das nicht, was das Problem ist, das ich mit persist() habe.

persist() garantiert auch, dass keine INSERT-Anweisung ausgeführt wird, wenn sie außerhalb der Transaktionsgrenzen aufgerufen wird. Dies ist nützlich bei langen 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äts" -Generator, nicht "Sequenz"), geschieht dieser INSERT sofort, egal Wenn Sie sich innerhalb oder außerhalb einer Transaktion befinden. Dies ist in einer lang laufenden Konversation mit einem erweiterten Sitzungs-/Persistenzkontext nicht gut.

147
Bala R

Ich habe mich eingehend mit save () und persist () befasst und es mehrere Male auf meinem lokalen Computer ausgeführt. Alle vorherigen Erklärungen sind verwirrend und nicht korrekt. Ich habe die Werte für save () und persist () nach gründlicher Recherche verglichen.

Save()

  1. Gibt die generierte ID nach dem Speichern zurück. Sein Serializable Rückgabetyp.
  2. Speichert den Wert sofort in der Datenbank und verfolgt die Entität bis zum Ende der Sitzung (Ich habe versucht, die Entitätswerte außerhalb der Transaktion zu ändern. Es zeigt keine Auswirkung, wenn die Sitzung festgeschrieben wird.)
  3. speichern Sie die Änderungen in der Datenbank außerhalb der Transaktion.
  4. Weist die generierte ID der Entität zu, die Sie beibehalten
  5. Session.save () für ein getrenntes Objekt erstellt eine neue Zeile in der Tabelle.

Persist()

  1. Gibt nach dem Speichern keine generierte ID zurück. Sein ungültiger Rückgabetyp.
  2. Speichert den Wert sofort in der Datenbank und verfolgt die Entität bis zum Ende der Sitzung. (Ich habe versucht, die Entitätswerte außerhalb der Transaktion zu ändern. Es zeigt keine Auswirkungen, wenn die Sitzung festgeschrieben wird.)
  3. Speichert die Änderungen nicht in der Datenbank außerhalb der Transaktion.
  4. Weist der Entität, die Sie beibehalten, den generated id Zu
  5. session.persist() für ein getrenntes Objekt wirft PersistentObjectException, da dies nicht zulässig ist.

Alle diese sind auf Hibernate v4.0.1 Getestet.

61
Zeus

Ich habe einige Scheintests durchgeführt, um den Unterschied zwischen save() und persist() aufzuzeichnen.

Klingt so, als ob diese beiden Methoden sich beim Umgang mit vorübergehenden Entitäten gleich verhalten, sich jedoch beim Umgang mit getrennten Entitäten unterscheiden.

Nehmen Sie für das folgende Beispiel EmployeeVehicle als Entität mit PK als vehicleId, das ein generierter Wert ist, 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 vorhandenes Objekt abrufen 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 dasselbe mit persist(entity) und erhalten Sie dasselbe mit neuer ID (sagen wir 37, honda);

Beispiel 2: Umgang mit losgelöstem Objekt

// 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: Sie erwarten möglicherweise, dass das in der vorherigen Sitzung erhaltene Fahrzeug mit der ID: 36 mit dem Namen "Toyota" aktualisiert wird. Aber was passiert ist, dass eine neue Entität in der DB gespeichert wird, mit einer neuen ID für und dem Namen "Toyota".

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

Verwenden von persist, um die 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 pk der Fahrzeugentität ein generierter Wert. Wenn Sie also save () verwenden, um eine getrennte Entität beizubehalten, generiert hibernate eine neue ID, um sie beizubehalten. Wenn dieses pk jedoch kein generierter Wert ist, führt dies zu einer Ausnahme, die angibt, dass ein Schlüssel verletzt wurde.

24

Diese Frage hat einige gute Antworten zu verschiedenen Persistenzmethoden in Hibernate. Um Ihre Frage direkt zu beantworten, wird mit save () die insert-Anweisung unabhängig vom Transaktionsstatus sofort ausgeführt. Der eingefügte Schlüssel wird zurückgegeben, sodass Sie Folgendes tun können:

long newKey = session.save(myObj);

Verwenden Sie also save (), wenn der persistenten Instanz sofort eine ID zugewiesen werden muss.

Mit persist () wird die Einfügeanweisung in einer Transaktion ausgeführt, nicht unbedingt sofort. Dies ist in den meisten Fällen vorzuziehen.

Verwenden Sie persist (), wenn Sie nicht möchten, dass die Einfügung außerhalb der Reihenfolge der Transaktion erfolgt, und wenn Sie nicht möchten, dass der eingefügte Schlüssel zurückgegeben wird.

12
CFL_Jeff

Hier sind die Unterschiede, die Ihnen helfen, die Persist-and-Save-Methode zu nutzen:

  • Der erste Unterschied zwischen save und persist ist der Rückgabetyp. Die Methode "return type of persist" ist ungültig, während die Methode "return type of save" ungültig ist
    Die Methode ist ein serialisierbares Objekt.
  • Die persist () -Methode garantiert nicht, dass der Bezeichnerwert sofort dem persistenten Status zugewiesen wird. Die Zuweisung kann zum Zeitpunkt des Flushs 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 Gesprächen mit einem erweiterten Sitzungskontext. Andererseits ist die Speichermethode in einer langen Unterhaltung mit einem erweiterten Sitzungskontext nicht gut.

  • Fünfter Unterschied zwischen der Methode save und persist in Hibernate: persist wird von JPA unterstützt, während save nur von Hibernate unterstützt wird.

Das vollständige Funktionsbeispiel finden Sie im Beitrag nterschied zwischen der Methode save und persist im Ruhezustand

5
David Pham

save () - Wie der Name der Methode andeutet, kann mit hibernate save () die Entität in der Datenbank gespeichert werden. 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 () - Hibernate persist ähnelt save (with transaction) und fügt das Entity-Objekt dem persistenten Kontext hinzu, sodass alle weiteren Änderungen nachverfolgt werden. Wenn die Objekteigenschaften geändert werden, bevor die Transaktion festgeschrieben oder die Sitzung gelöscht 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 kaskadierte Objekte berücksichtigt. Schließlich gibt persist nichts zurück, sodass wir das persistierte Objekt verwenden müssen, um den generierten Bezeichnerwert abzurufen.

5
Rohit Goyal

Hier ist der Unterschied:

  1. sparen:

    1. gibt die ID/ID zurück, wenn das Objekt in der Datenbank gespeichert wird.
    2. wird auch gespeichert, wenn versucht wird, dasselbe zu tun, indem eine neue Sitzung geöffnet wird, nachdem die Verbindung getrennt wurde.
  2. Fortdauern:

    1. wird ungültig, wenn das Objekt in der Datenbank gespeichert wird.
    2. wird PersistentObjectException auslösen, wenn versucht wird, das getrennte Objekt über eine neue Sitzung zu speichern.
5
Mohammed Amen

Tatsächlich hängt der Unterschied zwischen den Methoden hibernate save () und persist () von der verwendeten Generatorklasse ab.
Wenn unsere Generatorklasse zugewiesen ist, gibt es keinen Unterschied zwischen save () und persist (). Da "zugewiesen" für den Generator bedeutet, dass wir als Programmierer den Primärschlüsselwert angeben müssen, um ihn in der Datenbank zu speichern Hibernate it self weist den Primärschlüssel-ID-Wert der Datenbank zu (außer dem zugewiesenen Generator) Der Datensatz wird normal in die Datenbank eingefügt
Aber es ist zu hören, dass die save () -Methode diesen Primärschlüssel-ID-Wert zurückgeben kann, der durch den Ruhezustand generiert wird, und wir können ihn durch sehen
long s = session.save (k);
In diesem Fall gibt persist () dem Client niemals irgendeinen Wert zurück und gibt void zurück.
persist () garantiert auch, dass keine INSERT-Anweisung ausgeführt wird, wenn sie außerhalb der Transaktionsgrenzen aufgerufen wird.
wobei als Save () INSERT sofort geschieht, egal ob Sie sich innerhalb oder außerhalb einer Transaktion befinden.

2
Hari Krishna

Grundregel besagt, dass:

Für Entitäten mit generierter Kennung:

save (): Gibt den Bezeichner einer Entität sofort zurück und macht das Objekt dauerhaft. Es wird also sofort eine Insert-Abfrage ausgelöst.

persist (): Gibt das persistente Objekt zurück. Es besteht kein Zwang, die Kennung sofort zurückzugeben, so dass nicht garantiert wird, dass der Einsatz sofort ausgelöst wird. Es kann sein, dass ein Einsatz sofort ausgelöst wird, es wird jedoch nicht garantiert. In einigen Fällen wird die Abfrage möglicherweise sofort ausgelöst, während sie in anderen Fällen zum Zeitpunkt des Löschens der Sitzung ausgelöst wird.

Für Entitäten mit zugewiesener Kennung:

save (): Gibt die ID einer Entität sofort zurück. Da der Bezeichner der Entität bereits zugewiesen ist, bevor save aufgerufen wird, wird insert nicht sofort ausgelöst. Es wird zur Sitzungsbereinigungszeit ausgelöst.

persist (): Gleich wie save. Es feuert auch Einsatz zur Spülzeit.

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.save(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 Anmerkung generiert hat, d. H. 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 das Fortbestehen innerhalb einer Transaktion aufgerufen wurden.

Die anderen Unterschiede zwischen "Speichern" und "Bestehen" sind:

  1. save () kann außerhalb einer Transaktion aufgerufen werden. Wenn ein zugewiesener Bezeichner verwendet wird, wird, da id bereits verfügbar ist, keine Einfügeabfrage sofort ausgelöst. Die Abfrage wird nur ausgelöst, wenn die Sitzung gelöscht wird.

  2. Wenn die generierte ID 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 über kaskadierte Entitäten verfügt, werden diese zu diesem Zeitpunkt nicht in db gespeichert. Sie werden gespeichert, wenn die Sitzung gelöscht wird.

  3. Wenn sich persist () außerhalb einer Transaktion befindet, wird insert nur ausgelöst, wenn die Sitzung gelöscht wird, unabhängig davon, welche Art von Kennung (generiert oder zugewiesen) verwendet wird.

  4. Wenn save über ein persistentes Objekt aufgerufen wird, wird die Entität mithilfe einer Aktualisierungsabfrage gespeichert.

2
Gaurav Kumar

Es wird vollständig auf der Grundlage der "Generator" -Typ-ID beim Speichern einer Entität beantwortet. Wenn der Wert für den Generator "zugewiesen" ist, bedeutet dies, dass Sie die ID angeben. Dann macht es keinen Unterschied im Ruhezustand zu speichern oder zu bestehen. Sie können mit jeder Methode gehen, die Sie wollen. Wenn der Wert nicht "zugewiesen" ist und Sie save () verwenden, erhalten Sie die ID als Rückgabe von der save () -Operation.

Eine weitere Prüfung besteht darin, ob Sie den Vorgang außerhalb des Transaktionslimits ausführen oder nicht. Weil persist () zu JPA gehört und save () für den Ruhezustand. Wenn Sie also persist () außerhalb der Transaktionsgrenzen verwenden, können Sie dies nicht tun und Ausnahmen in Bezug auf persistenten Code auslösen. während mit save () keine solche Einschränkung besteht und man mit DB-Transaktion durch save () außerhalb des Transaktionslimits gehen kann.

1
Neeraj