Persist and merge are for two different purposes (they aren't alternatives at all).
(edited to expand differences information)
persist:
- Insert a new register to the database
- Attach the object to the entity manager.
merge:
- Find an attached object with the same id and update it.
- If exists update and return the already attached object.
- If doesn't exist insert the new register to the database.
persist() efficiency:
- It could be more efficient for inserting a new register to a database than merge().
- It doesn't duplicates the original object.
persist() semantics:
- It makes sure that you are inserting and not updating by mistake.
Example:
{ AnyEntity newEntity; AnyEntity nonAttachedEntity; AnyEntity attachedEntity; // Create a new entity and persist it newEntity = new AnyEntity(); em.persist(newEntity); // Save 1 to the database at next flush newEntity.setValue(1); // Create a new entity with the same Id than the persisted one. AnyEntity nonAttachedEntity = new AnyEntity(); nonAttachedEntity.setId(newEntity.getId()); // Save 2 to the database at next flush instead of 1!!! nonAttachedEntity.setValue(2); attachedEntity = em.merge(nonAttachedEntity); // This condition returns true // merge has found the already attached object (newEntity) and returns it. if(attachedEntity==newEntity) { System.out.print("They are the same object!"); } // Set 3 to value attachedEntity.setValue(3); // Really, now both are the same object. Prints 3 System.out.println(newEntity.getValue()); // Modify the un attached object has no effect to the entity manager // nor to the other objects nonAttachedEntity.setValue(42);}
This way only exists 1 attached object for any register in the entity manager.
merge() for an entity with an id is something like:
AnyEntity myMerge(AnyEntity entityToSave) { AnyEntity attached = em.find(AnyEntity.class, entityToSave.getId()); if(attached==null) { attached = new AnyEntity(); em.persist(attached); } BeanUtils.copyProperties(attached, entityToSave); return attached;}
Although if connected to MySQL merge() could be as efficient as persist() using a call to INSERT with ON DUPLICATE KEY UPDATE option, JPA is a very high level programming and you can't assume this is going to be the case everywhere.