Instead of implementing this by loading entity state separately, you could make use of Blaze-Persistence Updatable Entity Views which is a library for developing DTOs on top of JPA that also implements support for optimistic locking.
Your use case should be supported already, though I don't have a very good integration for Spring WebMvc yet, so you will have to do some plumbing yourself for now. I have something in mind for this though, it's just a matter of time and interested parties until the integration will be smoother.
Updatable entity views allow to map a subset of entities and also only flush that subset back. Thanks to the use of dirty tracking, it knows exactly what changed, allowing for fine grained flushing.
So the idea for PATCH support, which is what you want here, is to just get an empty reference by id for an object. Being empty means, that it has no data i.e. all null values. The dirty tracking assumes the initial state is all null then. You can simply map a request payload onto this object, if a value is null, it won't recognize it as being changed, thus ignore it. If anything non-null was set, it determines that such a field is dirty and on flush, only flushes dirty values.
I haven't tried it myself yet, but you could do something like this
// Create reference for the id, the object is empty i.e. all null except for the id
CustomerDTO dto = entityViewManager.getReference(CustomerDTO.class, someId);
// Map the payload on the DTO which will call setFoo(null) but that's ok, because that isn't considered being dirty
jsonMapper.map(requestPayload, dto);
// Flush dirty changes i.e. non-null values
entityViewManager.update(entityManager, dto);
The executed update query when using the PARTIAL
flush mode will only contain set clauses for properties with non-null values. The DTO would look like this
@EntityView(Customer.class)
@UpdatableEntityView(mode = FlushMode.PARTIAL)
public interface CustomerDTO {
@IdMapping Integer getId();
String getName();
void setName(String name);
String getDesc();
void setDesc(String desc);
}
If nothing is dirty, it won't even execute a query.