While using Hibernate with Spring Boot JPA, I noticed that when trying to implement an update method in a repository artifact that extends Spring's CrudRepository interface, that the entire entity object to be updated must be passed in to such an update method. Just intuitively that seemed wasteful and I wanted to know what is a clean way to get Spring Data/JPA to assume that only those values passed in need updating and to leave those not passed in untouched.
This is the service method as it stands right now,
public void updateCustomer(Long id, Customer customer) throws Exception {
customerRepository.save(customer);
}
In JPA you pass the entity and the framework figures out which properties you have changed. If you did not already know this I would suggest that you spent a little more time reading about the fundamentals of JPA. On the surface JPA looks easy and approachable, but if you don't understand the principles it is built on, you will end up spending a lot of time debugging and googling to decipher the error messages.
When an entity is managed JPA will take a copy of the object when it was loaded, and then compare it to the version passed to save/persist and figure out which columns should be updated. This makes for an easy-to-use developer model, where you (often) don't have to think about the changes to your entities.
You may think, as Rob suggest, that loading a single entity to change a single property is wasteful, but this is not always the case. Both EclipseLink and Hibernate uses a shared (2nd level) cache by default, so if an entity has been loaded already, it may be loaded from memory instead of the DB, and once you have modified the entity, JPA compares two objects in memory and generates the SQL needed to modify columns.
Some times you need to optimize you JPA code (but only when you have measured which operations are slow). A classical scenario is bulk delete/update, where you don't want JPA to spend time reading/copying/managing entities which you are deleting/updating. In those cases you can use delete or update queries, instead of loading the entity and calling EntityManager.remove() or modifying the entity inside a transaction. However you should be aware that this bypasses EntityListeners and cascade instructions as these are only called for managed entities.