美文网首页
springdataJPA更新操作如何防止丢失数据

springdataJPA更新操作如何防止丢失数据

作者: 杨少侠_Y | 来源:发表于2018-09-05 10:33 被阅读0次

    当用springdatajpa自带save()进行更新操作时,会先在底层执行merge()的一个动作,而执行merge动作时根据entiy标签里面的@ID,也就是主键来区分的,所以正确的更新方式是先把对应的entiy查询出来,然后在更新某个字段。
    这就引申出一个问题,假如我们直接使用实体对象来接收更新参数,所以我们并不知道哪个字段被更改掉。这就涉及到新老数据的对比操作。虽然我们可以直接使用BeanUtils.copyProperties(oldEntiy,newEntiy);来进行数据拷贝,但在不注意情况下就会出现丢失数据的情况。
    如何防止这种情况呢。这里可以运用java的反射机制来处理这种情况。话不多说,直接上代码:

    import java.beans.IntrospectionException;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * @author lqyang
     * @Title: SPRING-JPA-DATA 更新操作时 校验数据是否为空 解决处理BeanUtils.copyProperties(obj1,obj2);为空数据的处理
     * @date 2018/8/217:00
     */
    public class FieldUtil<T> {
    
        private T  entity;
    
        public FieldUtil(T entity){
            this.entity = entity;
        }
    
        /**
         * 使用案例:
         *   SysUserEntity sysUserEntity = sysUserDao.findOne(user.getUserId());
         *      BeanUtils.copyProperties(sysUserEntity,user);
         *      if(sysUserEntity != null){
         *      for(Field f : user.getClass().getDeclaredFields()){
         *          f.setAccessible(true);
         *              if(f.get(user) == null){
         *              String name = f.getName();
         *              FieldUtil<SysUserEntity> fieldUtil = new FieldUtil<>(user);
         *              fieldUtil.doInitEntity(name,sysUserEntity);
         *      }
         *  }
         *      sysUserDao.save(user);
         *  }else {
         *      user.setUserId(StringUtil.uuid());
         *  sysUserDao.save(user);
         *  }
         * @param methodName
         * @param object
         * @throws InvocationTargetException
         * @throws IllegalAccessException
         * @throws NoSuchFieldException
         * @throws IntrospectionException
         */
        public  void doInitEntity(String methodName,Object object) throws InvocationTargetException, IllegalAccessException, NoSuchFieldException, IntrospectionException {
            //根据传入的属性名称构造属性的set方法名
            String str = methodName.substring(0, 1).toUpperCase()+methodName.substring(1);
            String methodNameNew = "set"+str;
            Method[] methods = entity.getClass().getMethods();
            for(Method method:methods){
                //如果方法同名则执行该方法(不能用于实体中有重载方法的情况)
                if(methodNameNew.equals(method.getName())){
                    Class<?>[] clazz = method.getParameterTypes();
                    String type = clazz[0].getName();
                    if(type.equalsIgnoreCase("java.lang.String")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity,(String)field.get(object));
                        }
                    }
                    else if(type.equalsIgnoreCase("java.util.Date")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity, (Date)field.get(object));
                        }
                    }
                    else if(type.equalsIgnoreCase("java.lang.Integer")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity, new Integer((Integer) field.get(object)));
                        }
                    }
                    else if(type.equalsIgnoreCase("java.lang.Float")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity, new Float((Float) field.get(object)));
                        }
                    }
                    else if(type.equalsIgnoreCase("java.lang.Boolean")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity, new Boolean((Boolean) field.get(object)));
                        }
                    }
                    else if(type.equalsIgnoreCase("java.math.BigDecimal")){
                        Field field = object.getClass().getDeclaredField(methodName);
                        field.setAccessible(true);
                        if(field.get(object) != null){
                            method.invoke(entity, (BigDecimal) field.get(object));
                        }
                    }
                }
            }
        }
    }
    

    使用案例

    @Transactional(rollbackFor = Exception.class)
        public void updateUser(SysUserEntity user)throws Exception {
            SysUserEntity sysUserEntity = sysUserDao.findOne(user.getUserId());
            //BeanUtils.copyProperties(sysUserEntity,user);
            if(sysUserEntity != null){
                for(Field f : user.getClass().getDeclaredFields()){
                    f.setAccessible(true);
                    if(f.get(user) == null){
                        String name = f.getName();
                        FieldUtil<SysUserEntity> fieldUtil = new FieldUtil<>(user);
                        fieldUtil.doInitEntity(name,sysUserEntity);
                    }
                }
                sysUserDao.save(user);
            }
        }
    

    相关文章

      网友评论

          本文标题:springdataJPA更新操作如何防止丢失数据

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