我们正在使用Spring MVC 4
。
假设我有一个名为Customer
的实体。该实体有几个属性,有些允许空值,有些则不允许。
我们还使用从远程客户端通过DTO
传递到CustomerDTO
的{{1}}对象(@RestController
)。
这是我遇到的问题。假设用户通过@RequestBody
:
PUT
一切都很好。但是,如果用户只想更新{
"id": 123,
"name": "ACME",
"desc": "Blah"
}
,则会传入:
name
客户现在{
"id": 123,
"name": "ACME 2"
}
中有一个允许的null
。
所以我的问题是,如果没有将desc
放入更新语句中,如果它没有传递给DTO,我怎么能让Spring / Hibernate?
我认为,问题在于Spring将以下内容视为同一件事:
desc
由于
答案 0 :(得分:0)
根据Is it possible to update only a subset of attributes on an entity using Spring MVC with JPA?,您似乎基本上有两个可行的选项:
@SessionAttibutes
答案 1 :(得分:0)
您可以使用Blaze-Persistence Updatable Entity Views来代替通过分别加载实体状态来实现此目的,它是在JPA之上用于开发DTO的库,该库还实现了对乐观锁定的支持。 您的用例应该已经得到支持,尽管我还没有与Spring WebMvc很好的集成,所以您现在必须自己做一些工作。不过,我有一些想法,在整合变得更加顺利之前,这只是时间问题和感兴趣的参与者。
可更新的实体视图允许映射实体的子集,并且也只能刷新该子集。由于使用了脏跟踪,它可以准确地知道发生了什么变化,从而可以进行细粒度的冲洗。
因此,您要在此处获得 PATCH支持的想法是,仅通过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);
}
如果没有脏东西,它甚至不会执行查询。