前言
在使用mybatis-plus过程中,有很多插件都特别优秀,不仅使我们代码更加优雅,也提升了效率。
其中有个批量插入的插件insertBatchSomeColumn使用起来也挺方便的,但是批量更新一直没有官方插件,网络上面也没有找到靠谱的,于是就参照mybatis-plus这些官方的方法自定义了一个批量更新的方法。
实现效果
案例:用户排序
最终更新语句:
UPDATE sys_user SET user_order = CASE id WHEN 1 THEN 1 WHEN 2 THEN 2 WHEN 3 THEN 3 WHEN 4 THEN 4 END WHERE tenant_id = 1 AND id IN (1,2,3,4)
批量新增插件的配置
定义一个自己的BaseMapper继承自mybatis-plus的BaseMapper,声明批量新增方法,如下:
public interface MyBaseMapper extends BaseMapper { /** * 批量插入 * * @param entityList 实体列表 * @return 影响行数 */ int insertBatchSomeColumn(Collection entityList); }
把批量新增方法添加到方法列表中:
/** * 通用方法注入 */ public class MySqlInjector extends DefaultSqlInjector { @Override public List getMethodList(Class> mapperClass) { List methodList = super.getMethodList(mapperClass); // 添加批量新增方法 methodList.add(new InsertBatchSomeColumn()); return methodList; } }
MybatisPlusConfig配置中注入bean:
@Bean public MySqlInjector mySqlInjector() { return new MySqlInjector(); }
业务Mapper继承自自定义的MyBaseMapper,则就可以使用批量新增方法了。
下面进入正题
updateBatchById实现
自定义方法枚举
参照官方的SqlMethod,创建枚举MySqlMethod,并定义批量更新方法,如下:
public enum MySqlMethod { UPDATE_BATCH_BY_ID("updateBatchById", "通过主键批量更新数据", "UPDATE %s n%s nWHERE %s IN %sn"); private final String method; private final String desc; private final String sql; MySqlMethod(String method, String desc, String sql) { this.method = method; this.desc = desc; this.sql = sql; } public String getMethod() { return this.method; } public String getDesc() { return this.desc; } public String getSql() { return this.sql; } }
自定义批量更新方法
定义UpdateBatchById继承自AbstractMethod,实现其抽象方法injectMappedStatement,功能就是拼接sql,具体实现如下:
/** * 通过ID批量更新 */ public class UpdateBatchById extends AbstractMethod { private static final long serialVersionUID = 4198102405483580486L; @Override public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) { MySqlMethod sqlMethod = MySqlMethod.UPDATE_BATCH_BY_ID; String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), this.sqlSet(tableInfo), tableInfo.getKeyColumn(), this.sqlIn(tableInfo.getKeyProperty())); SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass); return this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource); } private String sqlSet(TableInfo tableInfo) { List fieldList = tableInfo.getFieldList(); StringBuilder sb = new StringBuilder(); for (TableFieldInfo fieldInfo : fieldList) { sb.append("") .append(fieldInfo.getColumn()).append(" =n") .append("CASE ").append(tableInfo.getKeyColumn()).append("n") .append("n") .append("WHEN #{et.").append(tableInfo.getKeyProperty()).append("} THEN #{et.").append(fieldInfo.getProperty()).append("}n") .append("n").append("END ,n") .append("n"); } return "n" + sb + ""; } private String sqlIn(String keyProperty) { StringBuilder sb = new StringBuilder(); sb.append("n") .append("#{et.").append(keyProperty).append("}") .append("n"); return sb.toString(); } }
到了这一步已经能够基本实现功能了,但是无法控制需要更新的字段,继续看下面。
自定义更新wrapper
自定义UpdateBatchWrapper继承自AbstractLambdaWrapper,此类主要为updateFields属性设置值,拼接sql的时候只对设置的属性更新,其他属性不变。
public class UpdateBatchWrapper extends AbstractLambdaWrapper> { private static final long serialVersionUID = 114684162001472707L; /** * 需要更新的字段 */ private List updateFields = null; @Override protected UpdateBatchWrapper instance() { this.updateFields = new ArrayList(); return this; } /** * 关键代码,为属性设置值 */ @SafeVarargs public final UpdateBatchWrapper setUpdateFields(SFunction... columns) { this.updateFields = Arrays.asList(columnsToString(columns).split(",")); return this; } public List getUpdateFields() { return updateFields; } }
参照批量新增把方法添加到方法列表
MyBaseMapper增加配置:
/** * 通过ID批量更新数据 * * @param entityList 实体列表 * @return 影响行数 */ int updateBatchById(@Param("list") Collection entityList, @Param("ew") Wrapper updateWrapper);
MySqlInjector增加配置:
// 添加批量更新方法 methodList.add(new UpdateBatchById());
测试updateBatchById
创建一个接口saveUserOrder实现用户排序,进而检查批量更新方法。
controller层
@PostMapping("saveUserOrder") @ApiOperation("用户排序") public Result saveUserOrder(@RequestBody List soList) { sysService.saveUserOrder(soList); return Result.success(); }
service层
@Override public void saveUserOrder(List soList) { // 业务实体转换为数据库实体 List userList = JSONUtil.toList(JSONUtil.toJsonStr(soList), SysUser.class); // 批量更新-设置更新字段为userOrder sysUserMapper.updateBatchById(userList, new UpdateBatchWrapper() .setUpdateFields(SysUser::getUserOrder)); }
OrderUserSO实体
@Data @ApiModel("用户排序业务实体") public class OrderUserSO implements Serializable { private static final long serialVersionUID = 509541044282315352L; @ApiModelProperty(value = "用户ID", required = true) @NotNull private Integer id; @ApiModelProperty(value = "用户顺序", required = true) @NotNull private Integer userOrder; }
见证奇迹的时刻到了…去文章开头见证奇迹吧。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持IT俱乐部。