TL; DR
The
merge()
receives a "common" object, which is not in the persistence context, and copies the properties of this object to the actual instance of the entity. Use it when you do not want to retrieve the entity and change its attributes manually.
Objects vs. Entities and the operation of the JPA
The first step to better understand how JPA works is to understand exactly how it handles the entities and states that these objects can take.
For this, I suggest reading my other answer on the subject .
Using merge
Basically, merge()
gets an object created outside of JPA, either directly in your code or in some automatic process like some JSON deserializer or an MVC framework that maps the request to a Java Bean .
Upon receiving this object, JPA checks whether an instance already exists in the context or retrieves one from the database.
Then it takes the values of the instance you passed and assigns it to the instance of the persistence context, effectively updating the data of the real entity. Note that it will update all the attributes and not only those that have value.
Then the merge()
method returns the updated entity to you. At this point, the object you passed to it may be dropped.
When using getReference()
The getReference()
returns a proxy for an entity that is in the database. Data is not loaded from the database immediately, other than the primary key. This proxy works like a lazy object that will only load the attributes of the entity when you call some getter
.
Finally, use this method when you want to avoid loading too much data from the database unnecessarily, such as in cases where you will only use one or two fields of an entity only if a particular condition is satisfied or when you need to pass an entity as parameter and possibly it is not used within the receiving method.
Anyway, the advantage is to postpone the transfer of data that you probably will not use. The disadvantage is that if you use the data, the "cost" is higher since you will have to make more queries to the bank.
Honestly, I have never seen a real need to use this method.
When using find()
The find()
method also returns an entity, however with the data already loaded, except of course lazy relationships.
Considerations
To recover an entity, the find()
method is almost always what you need. Use find()
by default, and if you have performance issues, then check what other method might help.
To upgrade an entity, use merge()
when you already have a populated object with all the new values that you save in the database.
For partial updates , use the find()
or getReference()
and its setter
of the property you want to update.