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();
    }

 

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