mybatis-plus批量更新updateBatchById問題
前言
在使用mybatis-plus過程中,有很多插件都特別優(yōu)秀,不僅使我們代碼更加優(yōu)雅,也提升了效率。
其中有個批量插入的插件insertBatchSomeColumn使用起來也挺方便的,但是批量更新一直沒有官方插件,網(wǎng)絡上面也沒有找到靠譜的,于是就參照mybatis-plus這些官方的方法自定義了一個批量更新的方法。
實現(xiàn)效果
案例:用戶排序

最終更新語句:
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<T> extends BaseMapper<T> {
/**
* 批量插入
*
* @param entityList 實體列表
* @return 影響行數(shù)
*/
int insertBatchSomeColumn(Collection<T> entityList);
}把批量新增方法添加到方法列表中:
/**
* 通用方法注入
*/
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
// 添加批量新增方法
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}MybatisPlusConfig配置中注入bean:
@Bean
public MySqlInjector mySqlInjector() {
return new MySqlInjector();
}業(yè)務Mapper繼承自自定義的MyBaseMapper,則就可以使用批量新增方法了。
下面進入正題
updateBatchById實現(xiàn)
自定義方法枚舉
參照官方的SqlMethod,創(chuàng)建枚舉MySqlMethod,并定義批量更新方法,如下:
public enum MySqlMethod {
UPDATE_BATCH_BY_ID("updateBatchById", "通過主鍵批量更新數(shù)據(jù)", "<script>UPDATE %s \n%s \nWHERE %s IN %s\n</script>");
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,實現(xiàn)其抽象方法injectMappedStatement,功能就是拼接sql,具體實現(xiàn)如下:
/**
* 通過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<TableFieldInfo> fieldList = tableInfo.getFieldList();
StringBuilder sb = new StringBuilder();
for (TableFieldInfo fieldInfo : fieldList) {
sb.append("<if test=\"ew.updateFields.contains("").append(fieldInfo.getColumn()).append("")\">")
.append(fieldInfo.getColumn()).append(" =\n")
.append("CASE ").append(tableInfo.getKeyColumn()).append("\n")
.append("<foreach collection=\"list\" item=\"et\" >\n")
.append("WHEN #{et.").append(tableInfo.getKeyProperty()).append("} THEN #{et.").append(fieldInfo.getProperty()).append("}\n")
.append("</foreach>\n").append("END ,\n")
.append("</if>\n");
}
return "<set>\n" + sb + "</set>";
}
private String sqlIn(String keyProperty) {
StringBuilder sb = new StringBuilder();
sb.append("<foreach collection=\"list\" item=\"et\" separator=\",\" open=\"(\" close=\")\">\n")
.append("#{et.").append(keyProperty).append("}")
.append("</foreach>\n");
return sb.toString();
}
}到了這一步已經(jīng)能夠基本實現(xiàn)功能了,但是無法控制需要更新的字段,繼續(xù)看下面。
自定義更新wrapper
自定義UpdateBatchWrapper繼承自AbstractLambdaWrapper,此類主要為updateFields屬性設置值,拼接sql的時候只對設置的屬性更新,其他屬性不變。
public class UpdateBatchWrapper<T> extends AbstractLambdaWrapper<T, UpdateBatchWrapper<T>> {
private static final long serialVersionUID = 114684162001472707L;
/**
* 需要更新的字段
*/
private List<String> updateFields = null;
@Override
protected UpdateBatchWrapper<T> instance() {
this.updateFields = new ArrayList<>();
return this;
}
/**
* 關鍵代碼,為屬性設置值
*/
@SafeVarargs
public final UpdateBatchWrapper<T> setUpdateFields(SFunction<T, ?>... columns) {
this.updateFields = Arrays.asList(columnsToString(columns).split(","));
return this;
}
public List<String> getUpdateFields() {
return updateFields;
}
}參照批量新增把方法添加到方法列表
MyBaseMapper增加配置:
/**
* 通過ID批量更新數(shù)據(jù)
*
* @param entityList 實體列表
* @return 影響行數(shù)
*/
int updateBatchById(@Param("list") Collection<T> entityList, @Param("ew") Wrapper<T> updateWrapper);MySqlInjector增加配置:
// 添加批量更新方法 methodList.add(new UpdateBatchById());
測試updateBatchById
創(chuàng)建一個接口saveUserOrder實現(xiàn)用戶排序,進而檢查批量更新方法。
controller層
@PostMapping("saveUserOrder")
@ApiOperation("用戶排序")
public Result saveUserOrder(@RequestBody List<OrderUserSO> soList) {
sysService.saveUserOrder(soList);
return Result.success();
}service層
@Override
public void saveUserOrder(List<OrderUserSO> soList) {
// 業(yè)務實體轉換為數(shù)據(jù)庫實體
List<SysUser> userList = JSONUtil.toList(JSONUtil.toJsonStr(soList), SysUser.class);
// 批量更新-設置更新字段為userOrder
sysUserMapper.updateBatchById(userList,
new UpdateBatchWrapper<SysUser>()
.setUpdateFields(SysUser::getUserOrder));
}OrderUserSO實體
@Data
@ApiModel("用戶排序業(yè)務實體")
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;
}見證奇跡的時刻到了…去文章開頭見證奇跡吧。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java中優(yōu)化大量if...else...方法總結
在我們平時的開發(fā)過程中,經(jīng)常可能會出現(xiàn)大量If else的場景,代碼顯的很臃腫,非常不優(yōu)雅,下面這篇文章主要給大家介紹了關于java中優(yōu)化大量if...else...方法的相關資料,需要的朋友可以參考下2023-03-03
springboot實現(xiàn)SSE(Server?Sent?Event)的示例代碼
SSE?全稱Server?Sent?Event,直譯一下就是服務器發(fā)送事件,本文主要為大家詳細介紹了springboot實現(xiàn)SSE的相關知識,需要的可以參考一下2024-04-04
Spring Boot2.0中SpringWebContext找不到無法使用的解決方法
這篇文章主要給大家介紹了關于Spring Boot2.0中SpringWebContext找不到無法使用的解決方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-12-12
springcloud3 Sentinel的搭建及案例操作方法
Sentinel是分布式系統(tǒng)流量控制的哨兵,阿里開源的一套服務容錯的綜合性解決方案,這篇文章主要介紹了springcloud3 Sentinel的搭建以及案例操作,需要的朋友可以參考下2023-01-01
Spring MVC保證Controller并發(fā)安全的方法小結
在 Spring MVC 中,默認情況下,@Controller 是單例的,這意味著所有請求共享一個 Controller 實例,為確保并發(fā)安全,Spring 并不會自動對 Controller 進行線程安全保護,本文給大家介紹了Spring MVC保證Controller并發(fā)安全的方法,需要的朋友可以參考下2024-11-11
Java+Spring+MySql環(huán)境中安裝和配置MyBatis的教程
這篇文章主要介紹了Java+Spring+MySql環(huán)境中安裝和配置MyBatis的教程,MyBatis一般被用來增強數(shù)據(jù)庫操作,文中對MyBatis的主配置文件有較為詳細的講解,需要的朋友可以參考下2016-04-04

