2017-05-08 117 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