编写自定义insert和update的SQL 批量处理方法
insert
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import java.util.List;
import java.util.function.Predicate;
/**
* @author aaa
* @date 2023-09-27 18:27
* @description
*/
public class InsertBatchColumn extends AbstractMethod {
/**
* 字段筛选条件
*/
@Setter
@Accessors(chain = true)
private Predicate predicate;
public InsertBatchColumn() {
super("insertBatch");
}
public InsertBatchColumn(Predicate predicate) {
// 此处的名称必须与后续的RootMapper的新增方法名称一致
super("insertBatch");
this.predicate = predicate;
}
@SuppressWarnings("Duplicates")
@Override
public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
List fieldList = tableInfo.getFieldList();
String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true,false) +
this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true,ENTITY_DOT, false) +
this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);
String keyProperty = null;
String keyColumn = null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if (tableInfo.havePK()) {
if (tableInfo.getIdType() == IdType.AUTO) {
/* 自增主键 */
keyGenerator = Jdbc3KeyGenerator.INSTANCE;
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
} else {
if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(modelClass.getName(), tableInfo, builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
}
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
// 注意第三个参数,需要与后续的RootMapper里面新增方法名称要一致,不然会报无法绑定异常
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, keyGenerator, keyProperty, keyColumn);
}
}
update
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* @author aaa
* @date 2023-09
* @description
*/
public class UpdateBatchColumn extends AbstractMethod {
/**
* @param methodName 方法名
* @since 3.5.0
*/
public UpdateBatchColumn(String methodName) {
super(methodName);
}
@SuppressWarnings("Duplicates")
@Override
public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {
String sql = "";
String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item", "item.") : "" + tableInfo.getLogicDeleteSql(true, true);
String setSql = sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, "item", "item.");
String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), "item." + tableInfo.getKeyProperty(), additional);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
// 第三个参数必须和RootMapper的自定义方法名一致
return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);
}
}
2,创建一个 SQL 注入器 InsertBatchSqlInjector
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.example.ftserver.plugin.InsertBatchColumn;
import com.example.ftserver.plugin.UpdateBatchColumn;
import java.util.List;
/**
* @author aaa
* @description
*/
public class CustomizedSqlInjector extends DefaultSqlInjector {
public List getMethodList(Class> mapperClass, TableInfo tableInfo) {
List methods = super.getMethodList(mapperClass,tableInfo);
// 自定义的insert SQL注入器
methods.add(new InsertBatchColumn());
// 自定义的update SQL注入器,参数需要与RootMapper的批量update名称一致
methods.add(new UpdateBatchColumn("updateBatch"));
return methods;
}
}
3,将SQL 注入器放入配置类
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author aaa
* @description
*/
@Configuration
@MapperScan(basePackages = "com.example.ftserver.mapper") // 不用配置.*
public class MybatisPlusConfig {
@Bean
public CustomizedSqlInjector sqlInjector(){
return new CustomizedSqlInjector();
}
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
return interceptor;
}
}
4,新建一个在 config 包下创建 RootMapper 接口,让其继承自 Mybatis Plus 提供的 BaseMapper, 并定义批量插入方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
/**
* @author aaa
* @date 2023-09-28 16:11
* @description
*/
public interface RootMapper extends BaseMapper {
// 新增方法
int insertBatch(@Param("list")Collection batchList);
// 修改方法
int updateBatch(@Param("list")Collection batchList);
}
5,新建 自己的Mapper,注意继承刚刚自定义的 RootMapper, 而不是Mybatis plus的 BaseMapper :
import com.test.ft.common.entity.PersonEntity;
import com.example.ftserver.plugin.RootMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* Mapper 接口
*
*
* @author aaa
* @since 2023-10-19 16:32:39
*/
public interface PersonMapper extends RootMapper {
}
批量修改会报错,Mybatis映射文件中的sql语句默认是不支持以" ; " 结尾,也就是不支持多条sql语句的执行。需要在连接mysql的url上加 &allowMultiQueries=true
运行批量操作才可以执行。
如果数据库设置了默认值,用批量添加汇会存null,修改如下:
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import java.util.List;
import java.util.function.Predicate;
/**
* @author aaa
* @date 2023-09-27 18:27
* @description
*/
public class InsertBatchColumn extends AbstractMethod {
/**
* 字段筛选条件
*/
@Setter
@Accessors(chain = true)
private Predicate predicate;
public InsertBatchColumn() {
super("insertBatch");
}
public InsertBatchColumn(Predicate predicate) {
// 此处的名称必须与后续的RootMapper的新增方法名称一致
super("insertBatch");
this.predicate = predicate;
}
@SuppressWarnings("Duplicates")
@Override
public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
List fieldList = tableInfo.getFieldList();
String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true, false) +
this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
/* String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) +
this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);*/
String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) +
this.filterTableFieldInfo(fieldList, predicate, i -> getInsertSqlProperty(i, ENTITY_DOT), EMPTY);
insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);
String keyProperty = null;
String keyColumn = null;
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
if (tableInfo.havePK()) {
if (tableInfo.getIdType() == IdType.AUTO) {
/* 自增主键 */
keyGenerator = Jdbc3KeyGenerator.INSTANCE;
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
} else {
if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(modelClass.getName(), tableInfo, builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
}
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
// 注意第三个参数,需要与后续的RootMapper里面新增方法名称要一致,不然会报无法绑定异常
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, keyGenerator, keyProperty, keyColumn);
}
private String getInsertSqlProperty(TableFieldInfo tableFieldInfo, final String prefix) {
String newPrefix = prefix == null ? "" : prefix;
String elPart = SqlScriptUtils.safeParam(newPrefix + tableFieldInfo.getEl());
//属性为空时使用默认值
String result = SqlScriptUtils.convertIf(elPart,
String.format("%s != null", newPrefix + tableFieldInfo.getEl()), false)
+ SqlScriptUtils.convertIf("default",
String.format("%s == null", newPrefix + tableFieldInfo.getEl()), false);
return result + ",";
}
}
总结
以上就是MyBatis plus对MySQL实现批量新增,批量修改的内容,才疏学浅,如有错误,希望多多的指正。需要注意的是:**该方法只对MySQL测试过,其他的数据库支持度不一致,不一定适用