JPA更新數據庫部分字段類似於mybatis(insertSelective)

(1)JPA自帶的接口更新和保存調用的都是同一個save(S)方法,是更新還是新增取決於傳入的對象主鍵相對於數據庫是否存在,如果存在則是更新,如果不存在,則是新增。

(2)但是JPA沒有類似Mybatis example的insertSelective()方法,因此手動寫了一個util用來對數據庫字段部分更新

(3)實現原理:剛開始想着更新的時候先從數據庫讀取原來的數據,然後通過BeanUtils.copyProperties(object1,object2)

(第一個參數爲傳遞來的新的對象,第二個參數爲從數據庫通過主鍵查詢到的對象。)

將前面的值賦給後面的值然後將後面的值進行數據庫提交,來實現更新,但是問題在於使用時,後者的對象會被前者爲null的字段覆蓋

比如傳遞過來的對象object1 的 name沒有設置值,那麼jpa會默認爲其設置爲null,所以使用上述方法的時候嗎,依舊會將我們從數據庫獲取的object2的name設置爲null,這顯然不是我們想要的,因此需要對該方法進行修改,後來發現BeanUtils.copyProperties()還有一個三個參數的方法BeanUtils.copyProperties(object1,object2,ignoreString) 第三個參數是忽略的屬性,也就是copy的時候不copy得屬性,這正好是我們需要用到的,第三個字段是擴展類型(String ... str) ,因此第三個參數除了可以使用(object1,object2,ignore1,ignore2)這種外,可以直接傳入數組,這顯然是非常美觀的,因此我們想辦法將忽略的屬性獲取到

具體實現原理:通過java反射object.getClass().getDeclaredFileds()獲取該對象的所有屬性,並與傳入的對象進行屬性字段匹配,判斷出該屬性是否爲空

我這裏新建了一個util可以複用,大家可以直接拷走

public class JudgeNullUtil {
    public static String[] getNullPropertiesArray(Object o1) throws IllegalAccessException {
        Field[] declaredFields = o1.getClass().getDeclaredFields();
        List<String> nullProperties = new ArrayList<>();
        for (Field declaredField : declaredFields) {
            //設置可以對private屬性的對象進行訪問
            declaredField.setAccessible(true);
            if(declaredField.get(o1)==null){
                // 將爲空的屬性添加到list中
                nullProperties.add(declaredField.getName());
            }
        }
        //nullProperties.stream().toArray(String[]::new);
        return nullProperties.toArray(new String[0]);
    }
}

具體調用的時候,在dao層或者service層,看具體需求,我的需求是下面的(我是直接在service調用的)

    public Role updateRole(Role role) throws IllegalAccessException {
        // 從數據庫獲取原有的值
        Optional<Role> byId = roleDao.findById(role.getId());
        if(byId.isPresent()){
            //如果optional其不爲空
            Role old = byId.get();
            System.out.println("前:"+JSONObject.toJSONString(old));
            // 獲取接收的對象爲空的屬性數組
            String[] ignore = JudgeNullUtil.getNullPropertiesArray(role);
            // 將前面的賦值給後面的
            BeanUtils.copyProperties(role,old,ignore);
            System.out.println("後"+JSONObject.toJSONString(old));
            return roleDao.save(old);
        }
        // 如果沒有修改成功就將原來的返回
        LOGGER.error("RoleService-updateRole異常,沒有更新成功");
        return byId.get();
    }

 

!就是如此
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章