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

Qualcuno può dirmi qual è il vantaggio di persist() vs save() in Hibernate?

Da questo post sul forum

persist() è ben definito. Rende persistente un’istanza transitoria. Tuttavia, non garantisce che il valore identificatore verrà assegnato immediatamente all’istanza persistente, l’assegnazione potrebbe avvenire al momento del flush. Le specifiche non dicono questo, che è il problema che ho con persist() .

persist() garantisce anche che non eseguirà un’istruzione INSERT se viene chiamata al di fuori dei limiti della transazione. Ciò è utile nelle conversazioni a lungo termine con un contesto esteso di sessione / persistenza.

È richiesto un metodo come persist() .

save() non garantisce lo stesso, restituisce un identificatore e se un INSERT deve essere eseguito per ottenere l’identificatore (ad es. generatore di “id quadro”, non “sequenza”), questo INSERT avviene immediatamente, non importa se ci si trova all’interno o al di fuori di una transazione. Questo non va bene in una lunga conversazione con un contesto esteso di sessione / persistenza.

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

Save()

  1. Restituisce l’ID generato dopo il salvataggio. Il suo tipo di ritorno Serializable .
  2. Salva immediatamente il valore nel DB e tiene traccia dell’ quadro fino alla fine della sessione (ho provato a cambiare i valori dell’entity framework al di fuori della transazione, non mostra alcun effetto quando la sessione esegue il commit)
  3. salva le modifiche al db al di fuori della transazione.
  4. Assegna l’id generato all’ quadro che stai persistendo
  5. Session.save () per un object distaccato creerà una nuova riga nella tabella.

Persist()

  1. Non restituisce l’ID generato dopo il salvataggio. Il suo tipo di ritorno vuoto.
  2. Salva immediatamente il valore nel DB e tiene traccia dell’entity framework fino alla fine della sessione. (Ho provato a modificare i valori dell’ quadro al di fuori della transazione, non mostra alcun effetto quando la sessione esegue il commit)
  3. Non salva le modifiche al db al di fuori della transazione.
  4. Assegna l’ generated id all’ quadro che stai persistendo
  5. session.persist() per un object distaccato genererà PersistentObjectException in quanto non consentito.

Tutti questi sono provati / testati su Hibernate v4.0.1 .

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

Sembra che entrambi questi metodi si comportino allo stesso modo quando si ha a che fare con Entità temporanea, ma differiscono quando si tratta di Entità distaccata.

Per l’esempio seguente, prendi EmployeeVehicle come Entity con PK come vehicleId che è un valore generato e vehicleName come una delle sue proprietà.

Esempio 1: gestione di oggetti transitori

 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) 

Notare che il risultato è lo stesso quando si ottiene un object 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: gestione dell’object scollegato

 // 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 il ​​veicolo con id: 36 ottenuto nella sessione precedente viene aggiornato con il nome “Toyota”. Ma quello che succede è che una nuova quadro viene salvata nel DB con un nuovo ID generato e Nome come “Toyota”

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

Usando persist per persistere quadro 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 caucanvas quando si ha a che fare con oggetti Transient.

Nota importante: nell’esempio sopra, il valore pk dell’entity framework veicolo è un valore generato, quindi quando si usa save () per mantenere un’ quadro distaccata, la modalità hibernate genera un nuovo id da persistere. Tuttavia, se questo pk non è un valore generato, viene generato un errore che indica la chiave violata.

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 che tu possa 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.

save () – Come suggerisce il nome del metodo, è ansible utilizzare hibernate save () per salvare l’ quadro nel database. Possiamo invocare questo metodo al di fuori di una transazione. Se usiamo questo senza transazione e abbiamo una cascata tra quadro, solo l’ quadro primaria viene salvata a meno che non si svuota la sessione.

persist () – Hibernate persist è simile al salvataggio (con transazione) e aggiunge l’object quadro al contesto persistente, quindi vengono monitorate eventuali ulteriori modifiche. Se le proprietà dell’object vengono modificate prima che la transazione venga confermata o la sessione venga scaricata, verrà anche salvata nel database. Inoltre, possiamo usare il metodo persist () solo all’interno del limite di una transazione, quindi è sicuro e si prende cura di qualsiasi object in cascata. Infine, persist non restituisce nulla, quindi è necessario utilizzare l’object persistente per ottenere il valore dell’identificatore generato.

Ecco le differenze che ti aiutano a trarre vantaggio dal metodo di salvataggio e salvataggio:

  • La prima differenza tra salvare e persistere è il tipo di ritorno. Il tipo di ritorno del metodo persist è nullo mentre restituisce il tipo di salvataggio
    il metodo è object serializzabile.
  • Il metodo persist () non garantisce che il valore identificatore verrà assegnato immediatamente allo stato persistente, l’assegnazione potrebbe avvenire al momento del flush.

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

  • Il metodo persist viene chiamato al di fuori dei limiti della transazione, è utile nelle conversazioni di lunga durata con un contesto di sessione esteso. D’altra parte, il metodo di salvataggio non è buono 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 operativo completo dal post Differenza tra salvare e persistere in Hibernate

Ecco la differenza:

  1. salvare:

    1. restituirà l’id / identificatore quando l’object viene salvato nel database.
    2. salverà anche quando l’object viene tentato di fare lo stesso aprendo una nuova sessione dopo che è stato staccato.
  2. Persistere:

    1. restituirà nulla quando l’object viene salvato nel database.
    2. getterà PersistentObjectException quando tenterà di salvare l’object staccato attraverso una nuova sessione.

In realtà la differenza tra i metodi hibernate save () e persist () dipende dalla class del generatore che stiamo usando.
Se viene assegnata la nostra class di generatore, non vi è alcuna differenza tra i metodi save () e persist (). Poiché il generatore “assegnato” significa, come programmatore, è necessario fornire il valore della chiave primaria per il salvataggio nel database corretto. Spero che tu conosca questo concetto di generatore. In caso di class generatrice diversa da quella assegnata, supponiamo che il nostro nome di class generatore sia Incremento hibernate it self assegnerà il valore id della chiave primaria nel database a destra [diverso dal generatore assegnato, hibernate usato solo per fare attenzione a ricordare il valore id della chiave primaria], quindi in questo caso se chiamiamo il metodo save () o persist () allora inserirà normalmente il record nel database
Ma senti cosa è, il metodo save () può restituire il valore id della chiave primaria che è generato dalla sospensione e possiamo vederlo con
long s = session.save (k);
In questo stesso caso, persist () non restituirà mai alcun valore al client, return void.
persist () garantisce anche che non eseguirà un’istruzione INSERT se viene chiamata al di fuori dei limiti della transazione.
dove Save () INSERT si verifica immediatamente, non importa se ci si trova all’interno o all’esterno di una transazione.

La regola di base dice che:

Per le quadro con identificatore generato:

save (): restituisce immediatamente l’identificatore di un’ quadro oltre a rendere persistente l’object. Quindi una query di inserimento viene triggersta immediatamente.

persist (): restituisce l’object persistente. Non ha alcuna costrizione a restituire immediatamente l’identificatore, quindi non garantisce che l’inserimento venga immediatamente triggersto. Potrebbe sparare un inserto immediatamente ma non è garantito. In alcuni casi, la query può essere triggersta immediatamente, mentre in altri può essere triggersta al momento del flush di sessione.

Per le quadro con identificatore assegnato:

save (): restituisce immediatamente l’identificatore di un’entity framework. Poiché l’identificatore è già assegnato all’entity framework prima di chiamare save, quindi insert non viene triggersto immediatamente. Viene sparato al momento del risciacquo della sessione.

persist (): uguale al salvataggio. Attacca anche l’inserto al momento del risciacquo.

Supponiamo di avere un’ quadro 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.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(); 

Supponiamo ora di avere la stessa quadro definita come segue senza che il campo id abbia generato un’annotazione, ad esempio 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 richiamati da una transazione.

Gli altri punti di differenza tra salvataggio e persistono sono:

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

  2. Se viene utilizzato l’identificatore generato, poiché l’ID deve essere generato, l’inserimento viene immediatamente triggersto. Ma salva solo l’ quadro primaria. Se l’ quadro ha alcune entity framework in cascata, quelle non verranno salvate in DB a questo punto. Saranno salvati quando la sessione verrà scaricata.

  3. Se persist () si trova all’esterno di una transazione, l’inserimento viene eseguito solo quando la sessione viene scaricata, indipendentemente dal tipo di identificatore (generato o assegnato) utilizzato.

  4. Se il salvataggio viene richiamato su un object persistente, l’ quadro viene salvata utilizzando la query di aggiornamento.

Ha completamente risposto sulla base del tipo di “generatore” in ID durante la memorizzazione di qualsiasi quadro. Se il valore per il generatore è “assegnato”, significa che stai fornendo l’ID. Quindi non fa diff in ibernazione per salvare o persistere. Puoi andare con qualsiasi metodo tu voglia. Se il valore non è “assegnato” e si utilizza save (), si otterrà l’ID come ritorno dall’operazione save ().

Un altro controllo è se si sta eseguendo l’operazione al di fuori del limite di transazione o no. Perché persist () appartiene a JPA mentre save () per l’ibernazione. Quindi usare persist () al di fuori dei limiti della transazione non permetterà di farlo e generare un’eccezione relativa al persistente. mentre con save () non esiste tale limitazione e si può andare con la transazione DB attraverso save () al di fuori del limite di transazione.