MyBatis-Plus:update 操作只更新客户端请求参数提供的列名

此文章发布于 36 个月前,部分信息可能已经过时,请自行斟酌确认。

应用场景

项目使用 mybatis-plus,客户端提交更新请求,有时只需要更新部分列,其中有的列要更新成 null,但 mybatis-plus 默认的更新行为会忽略 null 的字段,当然这个可以通过配置更新策略 updateStrategy 来调整,此文不讨论。

解决方案

最终我设计的方案:客户端提供了哪几列,就只更新这几列,包括 null 值也要更新。

思路:

1、获取 request 请求原始 json 信息,遍历 key 通过 UpdateWrapperset 方法构建 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);
    }
}
最后修改:2021 年 10 月 14 日 09 : 24 AM
如果觉得我的文章对你有用,请随意赞赏

发表评论