问题背景
使用mybatis-plus进行数据库交互,默认开启null不更新设置,在新增数据后,编辑页面将字段值清除后(date类型,int类型,为避免默认值传入,model全部使用包装类型初始化为null)无法将null值更新至数据库
单个解决方案
通过UpdateWrapper的set方法强制字段为null值
通用解决方法
定义基础类BaseModel,增加属性updateFieldList,model继承此类
代码语言:javascript复制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;
}
}
自定自定义注解UpdateRequestBody替代RequestBody
代码语言:javascript复制 @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;
}
自定义HandlerMethodArgumentResolver对前台json至后台Model转换的拦截,需要对List类型的Model集合进行支持,获取前台提交json对应定义Model中有同名属性的,进行加入打待更新字段列表updateFieldList
代码语言:javascript复制public class BaseModelMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
if (methodParameter.hasParameterAnnotation(UpdateRequestBody.class)) {
//集合
if(List.class.isAssignableFrom(methodParameter.getParameterType())){
ParameterizedType parameterizedType = (ParameterizedType) methodParameter.getGenericParameterType();
Class clazz = (Class)parameterizedType.getActualTypeArguments()[0];
//取出List中的真实对象类型
if(BaseModel.class.isAssignableFrom(clazz)){
return true;
}else{
return false;
}
}else{
//单个对象
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);
}
}
}
将自定义BaseModelMethodArgumentResolver 加入到配置中去
代码语言:javascript复制public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new BaseModelMethodArgumentResolver());
}
}
进行自定义UpdateWrapper构造
代码语言:javascript复制 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;
}
注:对标记TableField忽略注解的字段可以优化,反射可以应用初始化时扫描加入缓存进行优化