2017-05-08 104 views
0

我有一个车辆具有许多属性(大约30+属性)的实体。Spring中的实体更新选项/ JPA

我想了解什么是更新具有大量字段属性的实体的最佳方法。

例如,如果像车辆一样的特定对象(即DB中的表格行)必须用新值更新,那么可能的选项是什么?

@Entity 
public class Vehicle { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "vehicle_id", updatable = false, nullable = false) 
    private Long vehicleId; 
    private String vehicleName; 
    private String makeYear; 
    private String makeLocation; 
    private String Brand; 
    //**20 such other attributes** 

    @ManyToOne(nullable=false) 
    private Warehouse warehouse; 
    //owner of the relationship 

    @OneToMany(mappedBy = "vehicle", fetch = FetchType.LAZY) 
    private Customer customers; 

    //other such @OneToMany attributes 

} 

选项1是

public void updateVehicle(Vehicle vehicle){ 
    vehicle_existing = vehicleRepo.findOne(vehicle.getVehicleId()); 
    vehicle_existing = vehicleRepo.save(bid); 
} 

但是这导致vehicle_existing的某些字段被过度写入到空/空如果在传递车辆对象不具有该特定字段在json中。

选项2有防守加法器和添加Bean的每一个特定的值,如果它不为空,如下

public void addVehicleValues(Vehicle vehicle, Vehicle vehicle_existing){ 
    if (vehicle.vehicleId !=null && !vehicle.vehicleId.isEmpty()){ 
     //add the vehicleId to the existing vehicle ID in DB 
     vehicle_existing.vehicleId = vehicle.vehicleId;  
    } 
    ** and so on for other fields ...including the @OneToMany associations 
} 

这似乎有些单调乏味和不高雅的,但可以工作,因为想法是只添加非空和非空字段,这就是这样做的。

选项3我记得是DTO,但我不确定这是否是正确的方向。

鉴于这些选项,更新具有大量字段的实体的一般做法是什么?我正在使用Spring & JPA,但我认为这是一个常见用例。

+0

休眠提供了一个'合并( )'方法,它应该根据你传入的信息正确地更新给定的对象。如果你想要插入的数据不完整,通常很糟糕,你应该首先获取想要更新的对象,然后更改所需的对象字段并插入/更新它 – XtremeBaumer

+0

是的,vehicleRepo.sa上面提到的ve(bid)包括JPA中的merge()。如果你看到我的Option1,那正是我正在做的,抓取和更新。但是,如果数据不完整且**有大量字段**通过上面提出的选项2进行选择性更新,则变得繁琐,因此提出问题:) – HopeKing

+0

“但是,这会导致vehicle_existing的某些字段被覆盖为空/如果车辆物体被传入,json中没有该特定区域,则为空。“这就是Spring的工作原理。如果JSON定义了您未在构造函数签名中声明的属性,则它们将为null。当使用Spring Data时,你可以定义@PersistenceConstructor。但我认为该功能仅在使用MongoDB时才可用。是否有任何其他方式可以告诉Spring如何从你的mysql数据库实例化对象? – Razvi

回答

1

我使用这个类:

public class NullAwareBeanUtil { 
    private static String[] getNullPropertyNames(Object source) { 
     final BeanWrapper src = new BeanWrapperImpl(source); 
     java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); 

     Set<String> emptyNames = new HashSet<>(); 
     for (java.beans.PropertyDescriptor pd : pds) { 
      Object srcValue = src.getPropertyValue(pd.getName()); 
      if (srcValue == null || srcValue instanceof Set<?> || srcValue instanceof List<?>) { 
       emptyNames.add(pd.getName()); 
      } 
     } 
     String[] result = new String[emptyNames.size()]; 
     return emptyNames.toArray(result); 
    } 

    // then use Spring BeanUtils to copy and ignore null 
    public static void copyProperties(Object src, Object target) { 
     BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); 
    } 
} 

,并在服务类,其中的“产品”是包含属性修改的对象:

Product productToUpdate = findOne(product.getId()); 

NullAwareBeanUtil.copyProperties(product, productToUpdate); 

Product updatedProduct = save(productToUpdate); 
+0

辉煌!谢谢。 – HopeKing