【问题标题】:How can I ignore missing properties in my DTO objects with Spring MVC?如何使用 Spring MVC 忽略 DTO 对象中缺少的属性?
【发布时间】:2015-01-27 20:03:06
【问题描述】:

我们正在使用Spring MVC 4

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

我们还使用了一个DTO 对象 (CustomerDTO),它从远程客户端通过@RequestBody 传递到我们的@RestController

这是我遇到的问题。假设用户通过PUT 传递以下内容:

{
    "id": 123,
    "name": "ACME",
    "desc": "Blah"
}

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

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

客户现在在desc 中有一个null,这是允许的。

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

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

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

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

谢谢

【问题讨论】:

标签: java hibernate spring-mvc dto


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您可以使用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 刷新模式时执行的更新查询将只包含具有非空值的属性的集合子句。 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);
    }
    

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

    【讨论】:

      猜你喜欢
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      • 2019-08-05
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多