Qual è il vantaggio di persist () vs save () in Hibernate?


Risposte:


154

Da questo post sul forum

persist()è ben definito. Rende persistente un'istanza transitoria. Tuttavia, non garantisce che il valore identificativo verrà assegnato immediatamente all'istanza persistente, l'assegnazione potrebbe avvenire al momento dello scaricamento. Le specifiche non lo dicono, che è il problema che ho persist().

persist()garantisce inoltre che non eseguirà un'istruzione INSERT se viene chiamata al di fuori dei limiti della transazione. Ciò è utile nelle conversazioni di lunga durata con un contesto di sessione / persistenza esteso.

È persist()richiesto un metodo simile .

save()non garantisce lo stesso, restituisce un identificatore e se un INSERT deve essere eseguito per ottenere l'identificatore (ad es. generatore di "identità", non "sequenza"), questo INSERT si verifica immediatamente, indipendentemente dal fatto che ci si trovi all'interno o all'esterno di una transazione. Questo non va bene in una conversazione di lunga durata con un contesto di sessione / persistenza esteso.


44
per aggiungere altro dallo stesso post, per lamentarsi: "Purtroppo, 5 anni dopo, questa discussione rimane ancora l'unica chiara fonte di informazioni su questo argomento. La documentazione di Hibernate, sebbene dettagliata, è nulla di tutto tranne che delle informazioni di utilizzo più banali. Perché l'ultimo post di Christian non è nella Sessione Javadoc è solo un altro mistero della documentazione di Hibernate. "
kommradHomer,

vuoi dire che il metodo persist () renderà l'entità in stato distaccato e save () in stato allegato?
Rekinyz,

2
di recente ho usato sia il salvataggio che il persistere in una mappatura bidirezionale uno-a-molti. ho scoperto che il salvataggio non viene eseguito in cascata sul figlio, ovvero solo il genitore viene salvato / inserito nella tabella. Tuttavia, persist ha completato il compito di salvare sia Parent che Child in una chiamata. Sto usando un ID composito non un ID generato.
arn-arn,

68

Ho fatto una buona ricerca su save () vs persist () incluso eseguirlo sul mio computer locale più volte. Tutte le spiegazioni precedenti sono confuse e non sono corrette. Ho confrontato save () e persist () di seguito dopo una ricerca approfondita.

Save()

  1. Restituisce l'ID generato dopo il salvataggio. SuoSerializable tipo di ritorno.
  2. salva le modifiche nel db al di fuori della transazione.
  3. Assegna l'id generato all'entità che stai persistendo
  4. Session.save () per un oggetto distaccato creerà una nuova riga nella tabella.

Persist()

  1. Non restituisce l'ID generato dopo il salvataggio. Il suo tipo di ritorno vuoto.
  2. Non salva le modifiche nel db al di fuori della transazione.
  3. Assegna l' generated identità a cui stai persistendo
  4. session.persist()per un oggetto distaccato verrà lanciato in PersistentObjectExceptionquanto non è consentito.

Tutti questi sono provati / testati Hibernate v4.0.1.


Vengono menzionati il ​​punto 3 per Save () e Persist () ma in realtà non sono gli stessi. Il metodo Persist () salva anche le modifiche in db al di fuori della transazione.
Ravi.Kumar,

2
quando ho
eseguito il

Quindi # 1 e # 5 sono la vera differenza tra i due? Se è necessario restituire un ID o creare una nuova riga, utilizzare Save()?
user2490003,

How Save () # 3 è possibile al di fuori della transazione
vikas singh

24

Ho fatto alcuni finti test per registrare la differenza tra save()e persist().

Sembra che entrambi questi metodi si comportino allo stesso modo quando si tratta di entità transitoria ma differiscono quando si tratta di entità distaccata.

Per l'esempio seguente, prendi EmployeeVehicle come Entità con PK come vehicleIdvalore generato evehicleName come una delle sue proprietà.

Esempio 1: trattare con un oggetto transitorio

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

Risultato:

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

Si noti che il risultato è lo stesso quando si ottiene un oggetto già persistente e lo si salva

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

Ripeti lo stesso usando persist(entity) e risulterà lo stesso con il nuovo ID (diciamo 37, honda);

Esempio 2: trattare con un oggetto distaccato

// 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();

Risultato: potresti aspettarti che il Veicolo con ID: 36 ottenuto nella sessione precedente sia aggiornato con il nome "Toyota". Ma ciò che accade è che una nuova entità viene salvata nel DB con un nuovo ID generato per e nome come "Toyota"

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

Utilizzo di persist per persistere entità distaccata

// (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();

Risultato:

Exception being thrown : detached entity passed to persist

Quindi, è sempre meglio usare Persist () piuttosto che Save () poiché save deve essere usato con attenzione quando si tratta di oggetti transitori.

Nota importante: Nell'esempio sopra, il pk dell'entità veicolo è un valore generato, quindi quando si utilizza save () per persistere un'entità staccata, l'ibernazione genera un nuovo ID per persistere. Tuttavia se questo pk non è un valore generato di quanto risulta in un'eccezione che indica la chiave violata.


13

Questa domanda ha alcune buone risposte sui diversi metodi di persistenza in Hibernate. Per rispondere direttamente alla tua domanda, con save () l'istruzione insert viene eseguita immediatamente indipendentemente dallo stato della transazione. Restituisce la chiave inserita in modo da poter fare qualcosa del genere:

long newKey = session.save(myObj);

Quindi usa save () se hai bisogno di un identificatore assegnato immediatamente all'istanza persistente.

Con persist (), l'istruzione insert viene eseguita in una transazione, non necessariamente immediatamente. Questo è preferibile nella maggior parte dei casi.

Utilizzare persist () se non è necessario che l'inserimento avvenga fuori sequenza con la transazione e non è necessario restituire la chiave inserita.


6

Ecco le differenze che possono aiutarti a comprendere i vantaggi dei metodi persist e save:

  • La prima differenza tra save e persist è il loro tipo di ritorno. Il tipo restituito del metodo persist è nullo mentre restituisce il tipo di salvataggio
    metodo è oggetto Serializable.
  • Il metodo persist () non garantisce che il valore identificativo verrà assegnato immediatamente allo stato persistente, l'assegnazione potrebbe avvenire al momento dello scaricamento.

  • Il metodo persist () non eseguirà una query di inserimento se viene chiamata al di fuori dei limiti della transazione. Mentre, il metodo save () restituisce un identificatore in modo che una query di inserimento venga eseguita immediatamente per ottenere l'identificatore, indipendentemente dal fatto che si trovi all'interno o all'esterno di una transazione.

  • Il metodo persist è chiamato al di fuori dei confini delle transazioni, è utile nelle conversazioni di lunga durata con un contesto di sessione esteso. D'altra parte, il metodo di salvataggio non è utile in una conversazione di lunga durata con un contesto di sessione esteso.

  • Quinta differenza tra il metodo save e persist in Hibernate: persist è supportato da JPA, mentre il salvataggio è supportato solo da Hibernate.

Puoi vedere l'esempio di lavoro completo dal post Differenza tra il metodo save e persist in Hibernate


Innanzitutto si dice "Il metodo persist () non eseguirà una query di inserimento se viene chiamato al di fuori dei limiti delle transazioni". Quindi dici "Il metodo persist è chiamato al di fuori dei confini delle transazioni, è utile nelle conversazioni di lunga durata con un contesto di sessione esteso". Non sono contraddittori? Non capisco.
Kumar Manish

@KumarManish Nel caso del metodo persist, al momento dello scaricamento si verifica una query di inserimento. Quindi è una delle migliori pratiche nelle conversazioni di lunga data
David Pham,

5

save () - Come suggerisce il nome del metodo, ibernare save () può essere utilizzato per salvare l'entità nel database. Possiamo invocare questo metodo al di fuori di una transazione. Se lo utilizziamo senza transazione e abbiamo un collegamento in cascata tra entità, viene salvata solo l'entità primaria a meno che non eseguiamo lo svuotamento della sessione.

persist () - Hibernate persist è simile al salvataggio (con transazione) e aggiunge l'oggetto entità al contesto persistente, quindi vengono monitorate eventuali ulteriori modifiche. Se le proprietà dell'oggetto vengono modificate prima del commit della transazione o della cancellazione della sessione, verrà salvata anche nel database. Inoltre, possiamo usare il metodo persist () solo all'interno del limite di una transazione, quindi è sicuro e si prende cura di tutti gli oggetti a cascata. Infine, persist non restituisce nulla, quindi è necessario utilizzare l'oggetto persistente per ottenere il valore dell'identificatore generato.


5

Ecco la differenza:

  1. Salva:

    1. restituirà l'id / identificativo quando l'oggetto viene salvato nel database.
    2. salverà anche quando si tenta di fare lo stesso l'oggetto aprendo una nuova sessione dopo che è stato staccato.
  2. Persistere:

    1. restituirà null quando l'oggetto viene salvato nel database.
    2. genererà PersistentObjectException quando si tenta di salvare l'oggetto disconnesso attraverso una nuova sessione.

Puoi per favore mostrare un esempio con uno snippet. Sarebbe utile.
Avikool91,

5

La regola di base dice che:

Per entità con identificativo generato:

save (): restituisce immediatamente l'identificatore di un'entità oltre a rendere persistente l'oggetto. Quindi una query di inserimento viene attivata immediatamente.

persist (): restituisce l'oggetto persistente. Non ha alcuna costrizione a restituire immediatamente l'identificatore, quindi non garantisce che l'inserzione venga immediatamente attivata. Potrebbe sparare immediatamente un inserto ma non è garantito. In alcuni casi, la query può essere attivata immediatamente mentre in altri può essere attivata al momento dello scaricamento della sessione.

Per entità con identificativo assegnato:

save (): restituisce immediatamente l'identificatore di un'entità. Poiché l'identificatore è già assegnato all'entità prima di chiamare save, quindi insert non viene attivato immediatamente. Viene attivato al momento dello scaricamento della sessione.

persist (): uguale a save. Spara anche l'inserto al momento dello scarico.

Supponiamo di avere un'entità che utilizza un identificatore generato come segue:

@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;
    }
}

Salva() :

    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();

persistere() :

    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();

Supponiamo ora di avere la stessa entità definita come segue senza che il campo ID abbia generato l'annotazione, ovvero che l'ID verrà assegnato manualmente.

@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;
    }
}

per 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();

per 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();

I casi precedenti erano veri quando il salvataggio o il persist erano chiamati all'interno di una transazione.

Gli altri punti di differenza tra save e persist sono:

  1. save () può essere chiamato al di fuori di una transazione. Se viene utilizzato l'identificatore assegnato, poiché l'id è già disponibile, quindi nessuna query di inserimento viene immediatamente attivata. La query viene generata solo quando la sessione viene scaricata.

  2. Se viene utilizzato l'identificatore generato, poiché è necessario generare l'id, l'inserimento viene immediatamente attivato. Ma salva solo l'entità primaria. Se l'entità ha alcune entità in cascata, queste non verranno salvate in db a questo punto. Verranno salvati quando la sessione viene scaricata.

  3. Se persist () è al di fuori di una transazione, insert viene attivato solo quando la sessione viene scaricata, indipendentemente dal tipo di identificativo (generato o assegnato) utilizzato.

  4. Se il salvataggio viene richiamato su un oggetto persistente, l'entità viene salvata utilizzando la query di aggiornamento.


2

In realtà, la differenza tra i metodi hibernate save () e persist () dipende dalla classe del generatore che stiamo usando.
Se viene assegnata la nostra classe di generatori, non vi è alcuna differenza tra i metodi save () e persist (). Poiché il generatore 'assegnato' significa, come programmatore dobbiamo fornire il valore della chiave primaria per salvare nel giusto database [Spero che tu conosca questo concetto di generatori] Nel caso di una classe del generatore diversa da quella assegnata, supponi che se il nostro nome della classe del generatore è Increment significa hibernate assegnerà il valore dell'ID della chiave primaria nel database a destra [diverso dal generatore assegnato, l'ibernazione usato solo per occuparsi del valore dell'ID della chiave primaria da ricordare], quindi in questo caso se chiamiamo il metodo save () o persist (), allora inserirà normalmente il record nel database.
Ma qui, cosa è, il metodo save () può restituire quel valore ID chiave primaria che viene generato da ibernazione e possiamo vederlo da
s = session.save (k);
In questo stesso caso, persist () non restituirà mai alcun valore al client, restituendo il tipo void.
persist () garantisce inoltre che non eseguirà un'istruzione INSERT se viene chiamata al di fuori dei limiti della transazione.
mentre in save (), INSERT si verifica immediatamente, indipendentemente dal fatto che tu sia all'interno o all'esterno di una transazione.


1

Ha risposto completamente sulla base del tipo "generatore" in ID durante la memorizzazione di qualsiasi entità. Se il valore per il generatore è "assegnato" significa che stai fornendo l'ID. Quindi non fa alcuna differenza nell'ibernazione per il salvataggio o la persistenza. Puoi andare con qualsiasi metodo tu voglia. Se il valore non è "assegnato" e si utilizza save (), si otterrà ID come ritorno dall'operazione save ().

Un altro controllo è se si sta eseguendo l'operazione al di fuori del limite di transazione o meno. Perché persist () appartiene a JPA mentre save () per l'ibernazione. Pertanto, l'utilizzo di persist () al di fuori dei confini delle transazioni non consentirà di farlo e di generare eccezioni relative a persistente. mentre con save () nessuna tale restrizione e si può andare con transazione DB tramite save () al di fuori del limite di transazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.