美文网首页
mybatic-plus 将字段更新为null 方法封装

mybatic-plus 将字段更新为null 方法封装

作者: 东本三月 | 来源:发表于2020-01-31 15:55 被阅读0次

1.说明

  • 该封装方法使用的UpdateWrapper构造器的set()进行功能实现.参考来源https://blog.csdn.net/weixin_42059737/article/details/87911469
  • 核心功能使用beanutils包实现.引用了自己写的ReflectionUtils工具类(详情见https://www.jianshu.com/p/4824a289798f)
  • 方法写在新创建的BaseServiceImpl类,该类继承于mybatic-plus提供的ServiceImpl类. BaseServiceImpl的抽象类为BaseIService,不再详细说明
  • 项目里的Service层实现类,只能通过继承BaseServiceImpl类才可以使用封装的方法.

2.代码

public class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M,T> implements BaseIService<M,T> {

    /**
     * 完整更新一个实体,为null的属性也将更新到数据库
     * 该方法不会更新model继承来的属性,如需,需要修改反射调用的方法
     * @param entity
     * @return
     */
    public Boolean updateIntact(T entity){
        Assert.isTrue(entity!=null ,"实体类为null",true);
        UpdateWrapper<T> wrapper=new UpdateWrapper<>();
        //限制id
        try {
            Object id=PropertyUtils.getProperty(entity,"id");
            Assert.isTrue( id!=null,"无法从实体类["+entity.getClass().getName()+"]获取的id的值,不能执行更新操作",true);
            wrapper.eq("id",id);
        } catch (Exception e) {
            throw new ErrorException("无法从实体类["+entity.getClass().getName()+"]获取的id的值");
        }
        //设置要更新的属性和属性值
        Map<String,Object> fieldAndValue= ReflectionUtils.getAllFieldAndValue(entity,false);
        for(Map.Entry<String,Object> temp:fieldAndValue.entrySet()){
            wrapper.set(temp.getKey(),temp.getValue());
        }
        return  super.update(wrapper);
    }

    /**
     * 将指定实体,指定的字段更新为null
     * @param entity
     * @param field
     * @return
     */
    public Boolean updateToNull(T entity,String...field){
        Assert.isTrue(entity!=null ,"实体类为null",true);
        Integer id=null;
        try {
            id=(Integer) PropertyUtils.getProperty(entity,"id");
            Assert.isTrue( id!=null,"无法从实体类["+entity.getClass().getName()+"]获取的id的值,不能执行更新操作",true);
        } catch (Exception e) {
            throw new ErrorException("无法从实体类["+entity.getClass().getName()+"]获取的id的值");
        }
        return updateToNull(id,field);
    }


    /**
     * 将指定id的数据的指定字段更新为null
     * @param id
     * @param field
     * @return
     */
    public Boolean updateToNull(Integer id,String...field){
        Assert.isTrue(id!=null,"未指定要更新数据的id");
        UpdateWrapper<T> wrapper=new UpdateWrapper<>();
        wrapper.eq("id",id);
        //设置要更新的属性和属性值
        for(String temp:field){
            Assert.isTrue(StringUtils.hasText(temp),"需要指定字段进行更新");
            Assert.isTrue(!temp.equals("id"),"不能将id字段设置为null");
            wrapper.set(temp,null);
        }
        return  super.update(wrapper);
    }


    /**
     * 判断一个对象里一些属性的值在数据库是否具有唯一性
     * @Param entity 实体对象
     * @param fields 字段名称
     * @return
     * @time 2019年10月14日16:30:30
     * @author authstr
     */
    @Override
    public  boolean isUnique(T entity, String... fields) {
        Assert.isTrue(entity!=null ,"实体类为null",true);
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        for(int i=0;i<fields.length;i++){
            String field=fields[i];
            Object value=null;
            try {
                value=PropertyUtils.getProperty(entity,field);
            } catch (Exception e) {
                throw new ErrorException("无法通过字段名["+fields+"]从实体类["+entity.getClass().getName()+"]获取值");
            }
            if(value==null){
                throw new ErrorException("通过字段名["+fields+"]从实体类["+entity.getClass().getName()+"]获取的值是null");
            }
            wrapper.eq(field,value);
        }
        //判断是否加上id限制
        try {
            Object id=PropertyUtils.getProperty(entity,"id");
            if(id!=null){
                wrapper.ne("id",id);
            }
        } catch (Exception e) {
            throw new ErrorException("无法从实体类["+entity.getClass().getName()+"]获取的id的值");
        }
        int count=super.count(wrapper);
        if(count==0) {
            return true;
        }else{
            return false;
        }
    }

}
  • getAllFieldAndValue方法代码

    /**
     * 获取指定对象的所有属性名称和属性值.可以设置为使用属性的get方法获取值
     * @param obj  要获取的对象
     * @param byMethod 是否使用属性的get方法获取属性值
     * @return
     */
    public static Map<String,Object>  getAllFieldAndValue(Object obj,Boolean byMethod){
        Map<String,Object> res=new HashMap<String, Object>();
            for (Field field : obj.getClass().getDeclaredFields()) {
                Object value=null;
                String name=field.getName();
                if(byMethod){
                    value=executeGetMethod(obj,name,true);
                }else{
                    try {
                        field.setAccessible(true);
                        value= field.get(obj);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        throw new ErrorException("无法执行["+name+"]的字段的取值");
                    }
                }
                res.put(name, value);
            }
        return res;
    }

/**
     * 调用对象中一个属性的get方法
     * @param obj  要操作的对象
     * @param fieldName 属性名称
     * @param isException 获取失败,是否抛出异常
     * @return 该get方法的执行结果
     * @time 2019年12月12日11:57:17
     * @author authstr
     */
    public static Object executeGetMethod(Object obj,String fieldName,Boolean isException){
        // 构造get方法名称
        Object value=null;
        String methodName ="get"+ fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        try {
            Method m = obj.getClass().getMethod(methodName);
            //执行
            value=m.invoke(obj);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            if(isException){
                throw new ErrorException("未发现字段["+fieldName+"]的get方法");
            }
        } catch (Exception e) {
            e.printStackTrace();
            if(isException){
                throw new ErrorException("无法执行["+fieldName+"]的get方法");
            }
        }
        return value;
    }
  • 主要使用的方法为updateIntact.

3. 注意点

  • 如需要实现更新model继承来的属性,将调用的getAllFieldAndValue方法改成getAllParentFieldAndValue即可.
  • getAllParentFieldAndValue方法代码
/**
     * 获取指定对象的所有属性名称和属性值,包括为从父类继承来的属性.可以设置为使用属性的get方法获取值
     * @param obj 要获取的对象
     * @param byMethod 是否使用属性的get方法获取属性值
     * @return
     */
    public static Map<String,Object>  getAllParentFieldAndValue(Object obj,Boolean byMethod){
        Map<String,Object> res=new HashMap<String, Object>();
        try {
            PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
            PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj);
            for (int i = 0; i < descriptors.length; i++) {
                String name = descriptors[i].getName();
                if (!"class".equals(name)) {
                    Object value=null;
                    if(byMethod){
                        value=executeGetMethod(obj,name,true);
                    }else{
                        value=propertyUtilsBean.getNestedProperty(obj, name);
                    }
                    res.put(name, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }
  • 在使用该方法进行数据的更新时, mybatic-plus提供的@TableField功能将无法正确生效.因此需要注意更新的字段不要涉及有@TableField注解的字段. 我采取的方法是将有@TableField注解的字段抽到model的父类中,在调用updateIntact方法时默认不对继承的属性进行处理.

相关文章

网友评论

      本文标题:mybatic-plus 将字段更新为null 方法封装

      本文链接:https://www.haomeiwen.com/subject/zapgthtx.html