JAX-RS + JPA,如何 update/merge 仅显示实体字段的子集?

JAX-RS + JPA, how to update/merge only a subset of an Entity's fields?

假设我有以下实体:

@Entity
@XmlRootElement
@XmlAccessorType( XmlAccessType.FIELD)
public class MyEntity {

    @Id
    @GeneratedValue
    private long id;

    private boolean field1;

    private boolean field2;

    private boolean field3;
}

假设我有一个 REST Web 服务,允许客户端 POST 部分或完全更新 MyEntity 资源。也许方法签名看起来像这样:

@POST
@Path("{id}")
public Response postMyEntity(@PathParam("id") long id, MyEntity myEntity)

下面是 JSON,客户端可能会使用它来仅更新 ID 为 101 的 MyEntity 的 "field2":

{
    "id": 101
    "field2": true
}

如果 JPA 知道在反序列化过程中只设置了 field2,那么我很乐意使用如下简单的代码来保持此更改:

entityManager.merge(myEntity);

但是,此操作会更新 field1、field2 和 field3。

人们通常如何确保在数据库中仅更新 REST 请求的 JSON/XML 中明确指定的字段?我读过有人在他们的网络服务中使用 DTO(而不是实体本身)并手动找出需要在相应实体上设置哪些字段......但是,这个用例似乎很常见,我很惊讶这需要 DIY 方法。

也许有更好的解决方案,但我决定强制我的 REST 服务生成和使用 DTO 而不是实体。我的 DTO 类 从不使用基元(整数而不是 int),这确保如果客户端省略 JSON/XML 属性,则相应的 DTO 字段将为空。

当我收到 POST 更新资源时,我:

  1. 从数据库中获取对应的Entity。
  2. 将所有非空字段从 DTO 复制到实体。
  3. 使用 JPA 的合并功能更新数据库。

当我收到资源的 GET 时,我:

  1. 从数据库中获取实体。
  2. 将实体中的所有字段复制到新的 DTO。
  3. Return 客户端的 DTO。

设置这个很乏味,因为它需要我:

  1. 创建一堆 DTO 类 与相应的实体 类.
  2. 几乎相同
  3. 编写逻辑以在 DTO 和实体之间进行转换。
  4. 继续保持这种混乱状态。

我想我可以从我的实体 类 中删除基元,而不是使用 DTO,并向这些字段添加非空约束。但是,我在几个地方读到 "bad idea" 将您的实体 类 直接暴露给 REST 客户端。所以我继续使用 DTO 解决方案,尽管我不是它的最大粉丝。