如何使用Sping Data JPA更新局部字段

問題描述

在更新數據時,有時候咱們只須要更新一部分字段,其餘字段保持不變。Spring Data JPA並未提供現成的接口,直接使用save()更新會致使其餘字段被Null覆蓋掉。java

解決辦法

一般有兩種方法解決此問題:sql

一、經過傳入對象的id,從數據庫中查詢獲得原始對象,而後將要修改的字段封裝到原始對象中。再以封裝後的對象爲參數進行save()。

代碼以下:數據庫

public FrontResult update(Evaluation evaluation) {
        // 從數據庫中獲取對象
        Evaluation original = evaluationRepo().findById(evaluation.getId());
        // 複製想要更改的字段值
        BeanUtils.copyProperties(evaluation, original, getNullPropertyNames(evaluation));
        // 更新操做
        evaluationRepo().save(original);
        return FrontResult.init(FrontResult.SUCCEED, "更新成功");
    }

 

使用的工具類以下(用於獲取未被修改的字段名): app

public class UpdateUtil {
    public 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) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
}

二、經過註解@Query本身實現sql語句。

注意:工具

在執行update或者delete方法時,必須加上註解@Modifying 和 @Transactional。lua

此處的Test要使用實體的類名,不是數據庫中的表名。spa

代碼以下:code

@Modifying
@Transactional
@Query("update Test a set " +
       "a.name = CASE WHEN :#{#testAre.name} IS NULL THEN a.name ELSE :#{#testAre.name} END ," +
       "a.age = CASE WHEN :#{#testAre.age} IS NULL THEN a.age ELSE :#{#testAre.age} END ," +
       "a.insertTime = CASE WHEN :#{#testAre.insertTime} IS NULL THEN a.insertTime ELSE :#{#testAre.insertTime} END ," +
       "a.spare =  CASE WHEN :#{#testAre.spare} IS NULL THEN a.spare ELSE :#{#testAre.spare} END " +
       "where a.id = :#{#testAre.id}")
int update(@Param("testAre") TestAre testAre);

 

通常字段比較多時我會選第一種方式,雖然多查了一次數據庫,可是省鍵盤。對象

相關文章
相關標籤/搜索