【问题标题】:What is the best way of mapping non-null fields between entity and DTO?在实体和 DTO 之间映射非空字段的最佳方法是什么?
【发布时间】:2018-09-19 07:14:44
【问题描述】:

我正在使用 HTTP PATCH 方法来编辑 JPA 实体。由于这是 PATCH,因此只会编辑未设置为 null 的字段。在 DTO 和实体之间仅映射非空字段的最佳方法是什么?给定的实体可能有多个字段 - 比如说 20 个或更多,所以我不想这样做:

if(dto.getFoo() != null) {
   entity.setFoo(dto.getFoo);
}

这种映射有什么智能机制吗?

我正在使用springboot:1.5.6.RELEASE

【问题讨论】:

  • 使用像 Dozer 这样的 bean 映射库怎么样?它遵循convention-over-configuration,但也是高度可配置的,包括跳过空值的选项(参见dozer.sourceforge.net/documentation/…)
  • 谢谢@crizzis,我考虑过推土机,但也许有更聪明的解决方案。

标签: java spring-boot jpa mapping dto


【解决方案1】:

Blaze-Persistence 可更新实体视图将是您正在寻找的更智能的解决方案;) Blaze-Persistence 是我工作的基于 JPA 的库。你的用例应该已经得到支持,虽然我还没有很好的 Spring WebMvc 集成,所以你现在必须自己做一些管道。不过,我对此有一些想法,这只是时间和相关方的问题,直到整合更加顺利。

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

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

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

// Create reference for the id, the object is empty i.e. all null except for the id
MyDto dto = entityViewManager.getReference(MyDto.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(MyEntity.class)
@UpdatableEntityView(mode = FlushMode.PARTIAL)
public interface MyDto {
  @IdMapping Integer getId();
  String getFoo();
  void setFoo(String foo);
}

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

【讨论】:

    猜你喜欢
    • 2021-07-24
    • 1970-01-01
    • 2021-10-28
    • 2012-01-05
    • 1970-01-01
    • 2017-12-13
    • 2015-03-19
    • 2021-11-20
    • 1970-01-01
    相关资源
    最近更新 更多