MyBatis-Plus 提供的 SQL 注入器 是核心扩展机制,通过 sqlInjector 全局配置项,将自定义的通用 SQL 方法注入到 MyBatis 容器中。 开发者可通过实现 ISqlInjector 接口或继承 AbstractSqlInjector 抽象类,扩展全局通用的数据库操作方法,弥补原生 CRUD 无法满足的复杂业务需求,实现全项目 Mapper 复用自定义方法。
SQL 注入器的核心价值是全局复用自定义 SQL 方法,区别于普通 Mapper .xml 自定义方法,通过注入器定义的方法可被所有继承基础 Mapper 的接口使用,无需重复编写。
MyBatis-Plus 为 SQL 注入提供了标准化的顶层接口与抽象类,是实现自定义方法的基础:
所有注入器的顶层规范,定义了 SQL 注入的核心方法,负责检查并完成方法注入:
public interface ISqlInjector {
/**
* 检查并注入 SQL 方法
* @param builderAssistant Mapper 构建助手
* @param mapperClass Mapper 接口的 Class 对象
*/
void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
}ISqlInjector 的默认抽象实现,封装了通用注入逻辑,推荐直接继承此类自定义注入器,无需重写核心注入逻辑。
MyBatis-Plus 内置的默认注入器,负责注入原生的 CRUD 方法(selectById、insert、update 等),自定义注入器必须继承此类以保留原生方法。
自定义 SQL 语句的核心载体,每一个自定义方法对应一个 AbstractMethod 子类,负责生成 SQL 语句、解析表信息、构建 MappedStatement(MyBatis 执行 SQL 的核心对象)。
通过完整步骤实现全局清空表、自定义插入、MySQL 批量插入三个通用方法,覆盖开发高频场景。
实现自定义 SQL 方法
继承 AbstractMethod,重写 injectMappedStatement 方法,编写自定义 SQL 逻辑。
DeleteAll
全局清空表方法
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;
/**
* 自定义全局方法:清空表数据
*/
public class DeleteAll extends AbstractMethod {
public DeleteAll() {
// 方法名,与 Mapper 方法保持一致
super("deleteAll");
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 编写 SQL:DELETE FROM 表名
String sql = "DELETE FROM " + tableInfo.getTableName();
// 构建 SQL 源
SqlSource sqlSource = createSqlSource(configuration, sql, modelClass);
// 注册删除类型的 MappedStatement
return addDeleteMappedStatement(mapperClass, methodName, sqlSource);
}
}MyInsertAll
自定义插入方法
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;
/**
* 自定义全局插入方法
*/
public class MyInsertAll extends AbstractMethod {
public MyInsertAll() {
super("myInsertAll");
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 拼接插入 SQL
String sql = "INSERT INTO " + tableInfo.getTableName() + " ("
+ tableInfo.getKeyColumn() + ","
+ tableInfo.getFieldList().stream().map(i -> i.getColumn()).collect(Collectors.joining(","))
+ ") VALUES ("
+ "#{entity.id},"
+ tableInfo.getFieldList().stream().map(i -> "#{entity." + i.getProperty() + "}").collect(Collectors.joining(","))
+ ")";
SqlSource sqlSource = createSqlSource(configuration, sql, modelClass);
return addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, NoKeyGenerator.INSTANCE, tableInfo.getKeyProperty(), tableInfo.getKeyColumn());
}
}MySQL 批量插入
MysqlInsertAllBatch
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* MySQL 专用批量插入方法
*/
public class MysqlInsertAllBatch extends AbstractMethod {
public MysqlInsertAllBatch() {
super("mysqlInsertAllBatch");
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 拼接基础 SQL
String sql = "INSERT INTO " + tableInfo.getTableName() + " ("
+ tableInfo.getKeyColumn() + ","
+ tableInfo.getFieldList().stream().map(i -> i.getColumn()).collect(Collectors.joining(","))
+ ") VALUES ";
// 单条数据占位符
String value = "(#{" + ENTITY + "." + tableInfo.getKeyProperty() + "},"
+ tableInfo.getFieldList().stream().map(i -> "#{" + ENTITY + "." + i.getProperty() + "}").collect(Collectors.joining(","))
+ ")";
// 生成 foreach 循环脚本
String foreachScript = SqlScriptUtils.convertForeach(value, "list", null, ENTITY, ",");
// 包裹 script 标签(MyBatis 动态 SQL 必须)
String finalSql = "<script>" + sql + foreachScript + "</script>";
SqlSource sqlSource = createSqlSource(configuration, finalSql, modelClass);
// 主键自增适配
KeyGenerator keyGenerator = tableInfo.getIdType() == IdType.AUTO ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
return addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, keyGenerator, tableInfo.getKeyProperty(), tableInfo.getKeyColumn());
}
}自定义 SQL 注入器
继承 DefaultSqlInjector,重写 getMethodList 方法,注册自定义的 SQL 方法:
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import java.util.List;
/**
* 自定义 SQL 注入器
*/
public class MyLogicSqlInjector extends DefaultSqlInjector {
/**
* 注册自定义方法
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
// 保留原生 CRUD 方法
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
// 添加自定义方法
methodList.add(new DeleteAll());
methodList.add(new MyInsertAll());
methodList.add(new MysqlInsertAllBatch());
return methodList;
}
}定义全局基础 Mapper
创建自定义基础 Mapper 接口,继承 BaseMapper 并声明自定义方法,所有业务 Mapper 只需继承此接口即可使用全局方法:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 全局基础 Mapper,所有业务 Mapper 继承此类
*/
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 清空表数据
*/
Integer deleteAll();
/**
* 自定义插入
*/
int myInsertAll(T entity);
/**
* MySQL 批量插入
* @param list 数据集合
*/
int mysqlInsertAllBatch(@Param("list") List<T> list);
}全局配置注入器
在 Spring Boot 配置文件中指定自定义 SQL 注入器,MyBatis-Plus 启动时会自动加载。
mybatis-plus:
global-config:
# 自定义 SQL 注入器全限定类名
sql-injector: com.example.config.MyLogicSqlInjector业务使用
业务 Mapper 直接继承 MyBaseMapper,无需额外配置即可调用自定义全局方法:
import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends MyBaseMapper<User> {
// 直接拥有 deleteAll、myInsertAll、mysqlInsertAllBatch 方法
}测试调用
@SpringBootTest
class InjectorTest {
@Autowired
private UserMapper userMapper;
@Test
void testCustomMethod() {
// 1. 清空表
userMapper.deleteAll();
// 2. 自定义插入
User user = new User();
user.setName("test");
userMapper.myInsertAll(user);
// 3. 批量插入
List<User> list = new ArrayList<>();
list.add(new User("张三"));
list.add(new User("李四"));
userMapper.mysqlInsertAllBatch(list);
}
}自定义通用查询 原生 CRUD 无法满足的多表关联、聚合查询、分组查询,可通过注入器实现全局通用方法。
数据库特有语法适配 适配 MySQL 批量插入、Oracle 序列、PostgreSQL 专属函数等数据库特性。
数据权限全局控制 动态拼接权限过滤 SQL,实现所有查询自动携带数据权限条件。
性能优化 自定义高效 SQL 语句,替代原生低效方法,提升大数据量操作性能。
遗留系统兼容 迁移老系统时,保留原有 SQL 语法结构,快速适配 MyBatis-Plus。
TableInfo MyBatis-Plus 解析实体类生成的表信息对象,包含表名、主键、字段列表等核心信息。
SqlScriptUtils 动态 SQL 工具类,快速生成 foreach、if 等 MyBatis 脚本标签。
KeyGenerator 主键生成器,适配自增主键、UUID、雪花算法等主键策略。
MappedStatement MyBatis 底层对象,封装 SQL 语句、参数类型、返回值类型。
方法名严格匹配 AbstractMethod 构造方法的名称、MyBaseMapper 方法名、注入的 MappedStatement 名称必须完全一致。
动态 SQL 标签 自定义 SQL 包含动态语法(foreach、if)时,必须用 <script> 标签包裹。
参数命名规范 批量操作时,@Param 注解推荐使用 list/collection/array,符合 MyBatis-Plus 默认规范。
版本兼容 MyBatis-Plus 3.x 版本用法一致,2.x 版本已废弃,建议使用 3.5.0 及以上稳定版本。
避免重复注入 注入器会自动检查重复方法,无需手动处理重复注入问题。
数据库兼容性 部分自定义 SQL(如 MySQL 批量插入)仅适配特定数据库,跨库项目需做兼容处理。
SQL 注入器是 MyBatis-Plus 最强大的扩展机制,核心价值是全局复用自定义 SQL 方法。
实现三步核心:继承 AbstractMethod 写 SQL → 继承 DefaultSqlInjector 注册方法 → 自定义 BaseMapper 声明方法。
适用于复杂查询、性能优化、数据权限、数据库适配等场景,大幅减少重复代码。
开发中需严格遵循方法名匹配、动态 SQL 标签、参数规范等规则,保证注入器正常工作。