JPA EntityManager: Perché usare persist() invece di merge()?
L'EntityManager.merge()`può inserire nuovi oggetti e aggiornare quelli esistenti.
Perché si dovrebbe voler usare persist()
(che può solo creare nuovi oggetti)?
920
3
Entrambi i modi aggiungeranno un'entità a un PersistenceContext, la differenza è in ciò che si fa con l'entità dopo.
Persist prende un'istanza di entità, la aggiunge al contesto e rende quell'istanza gestita (cioè i futuri aggiornamenti dell'entità saranno tracciati).
Merge crea una nuova istanza della vostra entità, copia lo stato dall'entità fornita e rende la nuova copia gestita. L'istanza che passate non sarà gestita (qualsiasi modifica apportata non sarà parte della transazione - a meno che non chiamiate nuovamente merge).
Forse un esempio di codice aiuterà.
Lo scenario 1 e 3 sono approssimativamente equivalenti, ma ci sono alcune situazioni in cui si vorrebbe usare lo scenario 2.
Ho notato che quando ho usato
em.merge
, ho ottenuto una dichiarazioneSELECT
per ogniINSERT
, anche quando non c'era nessun campo che JPA stava generando per me - il campo chiave primaria era un UUID che ho impostato io stesso. Sono passato aem.persist(myEntityObject)
e ho ottenuto solo dichiarazioniINSERT
.Stavo ottenendo eccezioni lazyLoading sulla mia entità perché stavo cercando di accedere a una collezione caricata pigramente che era in sessione.
Quello che avrei fatto era in una richiesta separata, recuperare l'entità dalla sessione e poi provare ad accedere a una collezione nella mia pagina jsp che era problematica.
Per alleviare questo, ho aggiornato la stessa entità nel mio controller e l'ho passata alla mia jsp, anche se immagino che quando ho salvato di nuovo in sessione sarà accessibile anche se
SessionScope
e non lancerà unaLazyLoadingException
, una modifica dell'esempio 2:Il seguente ha funzionato per me: