如何使用 Spring MVC 忽略我的 DTO 对象中缺少的属性?

How can I ignore missing properties in my DTO objects with Spring MVC?

我们正在使用 Spring MVC 4

假设我有一个名为 Customer 的实体。该实体有几个属性,有些允许空值,有些则不允许。

我们还使用了一个 DTO 对象 (CustomerDTO),它通过 @RequestBody.

从远程客户端传递到我们的 @RestController

这是我遇到的问题。假设用户通过 PUT:

输入以下内容
{
    "id": 123,
    "name": "ACME",
    "desc": "Blah"
}

一切都很好。但是如果用户只想更新 name,他们会传入:

{
    "id": 123,
    "name": "ACME 2"
}

客户现在在允许的 desc 中有一个 null

所以我的问题是,如果 Spring/Hibernate 没有传递到 DTO,我怎样才能让 desc 甚至不把 desc 放在更新语句中?

我认为问题在于 Spring 将以下内容视为同一件事:

{
    ...
    "desc": null,
    ...
}

{
    ...
    ...   <desc omitted>
}

谢谢

基于Is it possible to update only a subset of attributes on an entity using Spring MVC with JPA?,看来您基本上有 2 个可行的选择:

  1. 从数据库中读取实体并更新特定字段
  2. 使用@SessionAttibutes

您可以使用 Blaze-Persistence Updatable Entity Views,而不是通过单独加载实体状态来实现它,这是一个用于在 JPA 之上开发 DTO 的库,它还实现了对乐观锁定的支持。 你的用例应该已经得到支持,虽然我还没有很好的 Spring WebMvc 集成,所以你现在必须自己做一些管道。不过,我对此有一些想法,这只是时间问题和感兴趣的各方,直到集成更加顺利。

可更新的实体视图允许映射实体的子集,并且也只刷新该子集。由于使用脏跟踪,它确切地知道发生了什么变化,允许细粒度的刷新。

因此 PATCH 支持 的想法就是通过对象的 id 获取空引用。为空意味着它没有数据,即所有空值。脏跟踪假定初始状态为空。您可以简单地将请求有效负载映射到此对象,如果值为空,它不会将其识别为已更改,因此将其忽略。如果设置了任何非空值,它确定这样的字段是脏的并且在刷新时,仅刷新脏值。

我自己还没有尝试过,但你可以这样做

// 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);
}

如果没有脏东西,它甚至不会执行查询。