【问题标题】:How can I "patch" a JPA entity?如何“修补”JPA 实体?
【发布时间】:2017-06-12 17:08:07
【问题描述】:

让我们假设一个 RESTful 服务收到一个PATCH 请求来更新一个可能有数十个字段的实体的一个或多个字段。

@Entity
public class SomeEntity {

  @Id
  @GeneratedValue
  private Long id;

 // many other fields
}

patch对应实体的一种肮脏方式是这样写:

SomeEntity patch = deserialize(json);
SomeEntity existing = findById(patch.getId());
if (existing != null) 
{
 if (patch.getField1() != null) 
 {
   existing.setField1(patch.getField1());
 }
 if (patch.getField2() != null) 
 {
   existing.setField2(patch.getField2());
 }
 if (patch.getField3() != null) 
 {
   existing.setField3(patch.getField3());
 }
}

但这太疯狂了!而且,如果我想将 1 修补到该实体的许多和其他关联上,那么精神错乱甚至会变得危险!

是否有一种理智而优雅的方式来完成这项任务?

【问题讨论】:

  • 如果要将null 设置为字段怎么办?
  • “JPA”与此有什么关系?这同样适用于任何带有字段的 Java 对象!

标签: java hibernate rest jpa


【解决方案1】:

与其通过自己编写逻辑来重新发明轮子,不如使用像 Dozer 这样的映射库?您想使用 'map-null' 映射属性:http://dozer.sourceforge.net/documentation/exclude.html

编辑我不确定是否可以将一个类映射到自身上。不过,您可以使用中间 DTO。

【讨论】:

    【解决方案2】:

    您可以发送一个包含要修补的字段名称的数组。然后,在服务器端,通过反射或任何字段映射,将每个字段设置为实体。我已经实现了它并且它有效,我认为我最好的建议是:

    不要发布端点来执行“通用”PATCH(修改),而是发布执行特定操作的端点。例如,如果您想修改员工的地址,请发布如下端点:

    PUT /employees/3/move
    

    需要带有新地址 {"address" : "new address"} 的 JSON。

    【讨论】:

      【解决方案3】:

      修改 SomeEntity 的 getter 并进行检查,如果任何值为空或 null 则返回对应的实体对象值。

      class SomeEntity {
          transient SomeEntity existing;
          private String name;
          public String getName(){
              if((name!=null&&name.length()>0)||existing==null){
                  return name;
              }
              return existing.getName();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-02
        • 2012-07-22
        • 1970-01-01
        • 2012-03-03
        相关资源
        最近更新 更多