Qual è la differenza tra persist () e merge () in JPA e Hibernate?


119

Qual è la differenza tra persist () e merge () in Hibernate?

persist() può creare una query UPDATE & INSERT, ad esempio:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

in questo caso la query verrà generata in questo modo:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

quindi il persist()metodo può generare un inserimento e un aggiornamento.

Adesso con merge():

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Questo è quello che vedo nel database:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

Ora aggiorna un record usando merge()

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setId(2);
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Questo è quello che vedo nel database:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley

7
Il javadoc è molto esplicito su ciò che fanno e quali sono le differenze. L'hai letto e capito?
skaffman


Risposte:


144

La specifica JPA contiene una descrizione molto precisa della semantica di queste operazioni, meglio che in javadoc:

La semantica dell'operazione persist , applicata a un'entità X è la seguente:

  • Se X è una nuova entità, diventa gestita. L'entità X verrà inserita nel database durante o prima del commit della transazione o come risultato dell'operazione di svuotamento.

  • Se X è un'entità gestita preesistente, viene ignorata dall'operazione persistente. Tuttavia, l'operazione di persistenza viene eseguita in cascata alle entità a cui fa riferimento X, se le relazioni da X a queste altre entità sono annotate con il valore dell'elemento di annotazione cascade=PERSISTo cascade=ALLo specificate con l'elemento descrittore XML equivalente.

  • Se X è un'entità rimossa, diventa gestita.

  • Se X è un oggetto distaccato, il EntityExistsExceptionpuò essere lanciato quando viene invocata l'operazione persist, oppure il EntityExistsExceptiono un altro PersistenceExceptionpuò essere lanciato al momento del flush o del commit.

  • Per tutte le entità Y a cui fa riferimento una relazione da X, se la relazione con Y è stata annotata con il valore dell'elemento a cascata cascade=PERSISTo cascade=ALL, l'operazione persistente viene applicata a Y.


La semantica dell'operazione di unione applicata a un'entità X è la seguente:

  • Se X è un'entità distaccata, lo stato di X viene copiato su un'istanza di entità gestita preesistente X 'della stessa identità oppure viene creata una nuova copia gestita X' di X.

  • Se X è una nuova istanza dell'entità, viene creata una nuova istanza dell'entità gestita X "e lo stato di X viene copiato nella nuova istanza dell'entità gestita X".

  • Se X è un'istanza dell'entità rimossa, IllegalArgumentExceptionverrà lanciata un'operazione di unione (o il commit della transazione fallirà).

  • Se X è un'entità gestita, viene ignorata dall'operazione di unione, tuttavia, l'operazione di unione viene applicata a cascata alle entità a cui fanno riferimento le relazioni da X se queste relazioni sono state annotate con il valore cascade=MERGEo l' cascade=ALLannotazione dell'elemento a cascata .

  • Per tutte le entità Y a cui fanno riferimento relazioni da X aventi il ​​valore dell'elemento a cascata cascade=MERGEo cascade=ALL, Y viene unito ricorsivamente come Y '. Per tutti questi Y referenziati da X, X 'è impostato come riferimento Y'. (Nota che se X è gestito, X è lo stesso oggetto di X '.)

  • Se X è un'entità unita a X ', con un riferimento a un'altra entità Y, dove cascade=MERGEo cascade=ALLnon è specificato, la navigazione della stessa associazione da X' produce un riferimento a un oggetto gestito Y 'con la stessa identità persistente di Y.


Grazie per le informazioni. Vedo la semantica di entrambe le definizioni. Ma la domanda riguarda le differenze tra loro. Forse presentare l'elenco degli stati e 2 sottosezioni per ogni diverso comportamento di persistvs merge?
AlikElzin-kilaka

25

Questo viene da JPA. In modo molto semplice:

  • persist(entity) dovrebbe essere usato con entità totalmente nuove, per aggiungerle al DB (se l'entità esiste già nel DB ci sarà il lancio di EntityExistsException).

  • merge(entity) dovrebbe essere utilizzato, per riportare l'entità al contesto di persistenza se l'entità è stata scollegata ed è stata modificata.


puoi per favore aggiungere una fonte alla tua spiegazione? Grazie.
AlikElzin-kilaka

@ AlikElzin-kilaka tale spiegazione, come ricordo, l'ho trovata in un libro "Beginning Java EE 7".
Krystian

12

Persist dovrebbe essere chiamato solo su nuove entità, mentre merge ha lo scopo di ricollegare le entità staccate.

Se stai utilizzando il generatore assegnato, l' utilizzo di merge invece di persist può causare un'istruzione SQL ridondante , influendo quindi sulle prestazioni.

Inoltre, anche la chiamata all'unione per le entità gestite è un errore poiché le entità gestite vengono gestite automaticamente da Hibernate e il loro stato viene sincronizzato con il record del database dal meccanismo di controllo sporco dopo aver scaricato il contesto di persistenza .


1

La differenza più importante è questa:

  • In caso di persistmetodo, se l'entità che deve essere gestita nel contesto della persistenza esiste già nel contesto della persistenza, quella nuova viene ignorata. (Non è successo niente)

  • Ma in caso di mergemetodo, l'entità che è già gestita nel contesto della persistenza verrà sostituita dalla nuova entità (aggiornata) e una copia di questa entità aggiornata tornerà indietro. (d'ora in poi tutte le modifiche dovrebbero essere apportate su questa entità restituita se si desidera riflettere le modifiche nel contesto della persistenza)

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.