Spring boot uses mybatis plus form to update null value

Background of problem

Use mybatis plus for database interaction. The default setting is to enable null without updating. After adding data, edit the page to clear the field value (date type, int type, in order to avoid the default value passing in, all model s are initialized to null with the packing type). Null value cannot be updated to the database

Single solution

Force the field to null through the set method of UpdateWrapper

General solutions

Define the basic class BaseModel, add the property updateFieldList, and the model inherits this class

public class BaseModel {
    @TableField(exist = false)
    @JSONField(serialize = false)
    private List<String> updateFieldList;

    public List<String> getUpdateFieldList() {
        return updateFieldList;
    }

    public void setUpdateFieldList(List<String> updateFieldList) {
        this.updateFieldList = updateFieldList;
    }
}

Custom annotation updaterequesbody replaces RequestBody

    @ResponseBody
    @PostMapping("/update")
    public Object update(@UpdateRequestBody AccountDO entity) {
        Result result = null;
        try {
            accountService.update(entity);
            result = Result.okResult();
        } catch (Exception e) {
            result = Result.errorResult();
        }
        return result;
    }

    @ResponseBody
    @PostMapping("/batchUpdate")
    public Object batchUpdate(@UpdateRequestBody List<AccountDO> entityList) {
        Result result = null;
        try {
            accountService.batchUpdate(entityList);
            result = Result.okResult();
        } catch (Exception e) {
            result = Result.errorResult();
        }
        return result;
    }

The user-defined HandlerMethodArgumentResolver intercepts the conversion of foreground json to background Model. It needs to support the Model collection of List type. To obtain the property with the same name in the Model corresponding to the definition of foreground json, add the field List to be updated updateFieldList

public class BaseModelMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        if (methodParameter.hasParameterAnnotation(UpdateRequestBody.class)) {
            //aggregate
            if(List.class.isAssignableFrom(methodParameter.getParameterType())){
                ParameterizedType parameterizedType = (ParameterizedType) methodParameter.getGenericParameterType();
                Class clazz = (Class)parameterizedType.getActualTypeArguments()[0];
                //take out List Real object types in
                if(BaseModel.class.isAssignableFrom(clazz)){
                    return true;
                }else{
                    return  false;
                }
            }else{
                //Single object
                if(BaseModel.class.isAssignableFrom(methodParameter.getParameterType())){
                    return true;
                }else{
                    return false;
                }
            }
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        String body = "";
        try {
            HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            body = CommonUtil.getBodyString(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(List.class.isAssignableFrom(methodParameter.getParameterType())){
            List resultList = new ArrayList();
            ParameterizedType parameterizedType = (ParameterizedType) methodParameter.getGenericParameterType();
            Class clazz = (Class)parameterizedType.getActualTypeArguments()[0];
            List<Field> fs = Arrays.asList(clazz.getDeclaredFields());
            JSONArray array = JSONArray.parseArray(body);
            for (Object temp:array) {
                JSONObject obj = JSONObject.parseObject(temp.toString());
                List<String> updateFieldList = new ArrayList<>();
                for (String key : obj.keySet()) {
                    for (Field filed : fs) {
                        if (key.toLowerCase().equals(filed.getName().toLowerCase())) {
                            updateFieldList.add(key.toLowerCase());
                            continue;
                        }
                    }
                }
                obj.put("updateFieldList",updateFieldList);
                resultList.add(obj);
            }
            return  JSONArray.parseArray(resultList.toString(),clazz);
        }else{
            Class clazz = methodParameter.getParameterType();
            List<String> updateFieldList = new ArrayList<>();
            List<Field> fs = Arrays.asList(clazz.getDeclaredFields());
            JSONObject obj = JSON.parseObject(body);
            for (String key : obj.keySet()) {
                for (Field filed : fs) {
                    if (key.toLowerCase().equals(filed.getName().toLowerCase())) {
                        updateFieldList.add(key.toLowerCase());
                        continue;
                    }
                }
            }
            obj.put("updateFieldList",updateFieldList);
            return JSON.parseObject(obj.toString(),clazz);
        }

    }
}

Add the custom BaseModelMethodArgumentResolver to the configuration

public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new BaseModelMethodArgumentResolver());
    }
}

Make a custom UpdateWrapper construction

 public <T extends BaseModel>  UpdateWrapper getUpdateWrapper(T entity){
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<T>();
        try{
           Class clazz = entity.getClass();
           List<Field> fs = Arrays.asList(clazz.getDeclaredFields());
           List<String> updateFieldList = entity.getUpdateFieldList();
           if(updateFieldList!=null){
               for (String updateFiled:updateFieldList ) {
                   for (Field field:fs) {
                       field.setAccessible(true);
                       if(field.getName().toLowerCase().equals(updateFiled)){
                           Object fieldValue = field.get(entity);
                           updateWrapper.set(fieldValue==null,field.getName(),null);
                           continue;
                       }
                   }
               }
           }
           return updateWrapper;
       }catch (Exception e){
           e.printStackTrace();
       }
        return updateWrapper;
    }

Note: fields marked with TableField that ignore annotation can be optimized. Reflection can be optimized by scanning and adding cache during initialization

Tags: Java JSON Database Mybatis

Posted on Sat, 21 Mar 2020 07:12:50 -0700 by kevin99