自己检查版本的替代方法是构建实体对象并调用entityManager.merge
,如果版本同时更改,它也应该触发乐观锁异常,但如果同时删除对象,它不会抛出。要正确处理,您必须自己检查。
您可以使用Blaze-Persistence 可更新实体视图而不是通过单独加载实体状态来实现这一点, 它是一个用于在 JPA 之上开发 DTO 的库,它还实现了对乐观锁定的支持。你的用例应该已经得到支持,虽然我还没有很好的 Spring WebMvc 集成,所以你现在必须自己做一些管道。不过,我对此有一些想法,这只是时间和相关方的问题,直到整合更加顺利。
可更新的实体视图允许映射实体的子集,并且只刷新该子集。由于使用了脏跟踪,它可以准确地知道发生了什么变化,从而可以进行细粒度的刷新。
所以PATCH support的想法,这似乎是你想要的,只是通过 id 获得一个对象的空引用。为空意味着它没有数据,即所有空值。脏跟踪假设初始状态全部为空。您可以简单地将请求有效负载映射到该对象上,如果值为 null,它不会将其识别为已更改,因此忽略它。如果设置了任何非空值,则它确定这样的字段是脏的,并且在刷新时,只刷新脏值。
我自己还没有尝试过,但你可以做这样的事情
// 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);
使用PARTIAL
刷新模式时执行的更新查询将仅包含具有非空值的属性的 set 子句。DTO 看起来像这样
@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);
}
如果没有脏东西,它甚至不会执行查询。