此文章发布于38
个月前,部分信息可能已经过时
,请自行斟酌确认。
应用场景
项目使用 mybatis-plus
,客户端提交更新请求,有时只需要更新部分列
,其中有的列要更新成 null
,但 mybatis-plus
默认的更新行为会忽略 null 的字段
,当然这个可以通过配置更新策略 updateStrategy
来调整,此文不讨论。
解决方案
最终我设计的方案:客户端提供了哪几列,就只更新这几列,包括 null 值也要更新。
思路:
1、获取 request
请求原始 json
信息,遍历 key
通过 UpdateWrapper
的 set
方法构建 set 子句
。
2、但 json
中的 key
名称是对应实体类的属性名称
而非数据库字段名
,所以需要将属性名转换为数据库字段名。
3、通过 LambdaUtils.getColumnMap(实体类.class)
可以获取到属性-字段名
的映射关系。
4、另外 requestBody 流只能读取一次,就需要封装可重复读的 RequestWrapper
(可参考开源项目 RuoYi)
最终核心代码:ProjectServiceImpl.java
@Transactional(rollbackFor = Exception.class)
@Override
public void edit(ProjectParam projectParam) {
//只修改提交的列
var request = HttpServletUtil.getRequest();
if (request instanceof RepeatedlyRequestWrapper) {
//获取原始请求 JSON 参数
var repeatedlyRequest = (RepeatedlyRequestWrapper) request;
JSONObject json = JSONObject.parseObject(HttpHelper.getBodyString(repeatedlyRequest));
//条件构造器
UpdateWrapper<Project> updateWrapper = new UpdateWrapper<>();
updateWrapper.lambda().eq(Project::getId, projectParam.getId());
Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(Project.class);
//遍历提交的参数,构造 set 片段
json.keySet().forEach(x -> {
var k = x.toUpperCase(Locale.ENGLISH); //columnMap 中的 Key 全大写
if (columnMap.containsKey(k)) {
var columnName = columnMap.get(k).getColumn();
updateWrapper.set(columnName, json.get(x));
}
});
//更新
this.update(updateWrapper);
}
}