1. SQL注入器扩展的背景与价值
在MyBatis-Plus框架中,SQL注入器是一个核心组件,它负责动态生成SQL语句。3.5.17版本作为当前稳定版本,与Spring Boot 2.7.x版本保持良好兼容性。SQL注入器扩展的意义在于:
- 解决原生MyBatis需要手动编写大量重复SQL的问题
- 提供标准化的SQL生成方式,避免不同开发者写法差异
- 支持快速扩展自定义SQL逻辑,满足特殊业务需求
实际开发中,我们经常遇到需要扩展默认SQL逻辑的场景。比如需要实现:
- 多租户数据隔离
- 逻辑删除的定制化处理
- 敏感字段自动加解密
- 审计字段自动填充
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. MyBatis-Plus 3.5.17版本核心特性解析
2.1 版本兼容性矩阵
| Spring Boot版本 | MyBatis-Plus版本 | 特性支持 |
|---|---|---|
| 2.7.x | 3.5.17 | 完整支持 |
| 3.0.x | 3.5.17 | 部分兼容 |
| 2.6.x | 3.5.17 | 推荐使用 |
2.2 SQL注入器工作流程
- 启动时扫描@Mapper接口
- 解析方法签名和注解
- 匹配对应的SQL模板
- 注入参数绑定逻辑
- 生成最终可执行SQL
关键点在于AbstractSqlInjector类,它定义了SQL语句的注入规则。我们扩展时需要重点关注:
- 方法名与SQL模板的映射关系
- 参数绑定的处理方式
- SQL片段的重用机制
3. 自定义SQL注入器实现指南
3.1 基础实现步骤
- 继承AbstractSqlInjector类
java复制public class CustomSqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
// 返回自定义方法列表
}
}
- 定义自定义方法
java复制public class CustomSelectMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(...) {
// 实现SQL生成逻辑
}
}
- 配置注入器
yaml复制mybatis-plus:
global-config:
sql-injector: com.example.CustomSqlInjector
3.2 实战案例:敏感字段加密
假设我们需要对phone字段自动加密:
java复制public class EncryptMethod extends AbstractMethod {
private static final String SQL_TEMPLATE = "SELECT * FROM %s WHERE AES_DECRYPT(phone, 'key') = #{phone}";
@Override
public MappedStatement injectMappedStatement(...) {
String sql = String.format(SQL_TEMPLATE, tableInfo.getTableName());
SqlSource sqlSource = languageDriver.createSqlSource(...);
return this.addSelectMappedStatement(...);
}
}
关键点:
- 使用数据库加密函数处理敏感字段
- 保持参数绑定的安全性
- 确保SQL注入防护
4. 高级扩展技巧与避坑指南
4.1 多租户实现方案
java复制public class TenantSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methods = super.getMethodList(mapperClass);
methods.add(new TenantSelect());
return methods;
}
}
public class TenantSelect extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(...) {
String originalSql = super.injectMappedStatement(...);
return originalSql + " WHERE tenant_id = #{tenantId}";
}
}
常见问题:
- 分页查询总数统计不准确
- 解决方案:重写PaginationInterceptor
- 连表查询漏加租户条件
- 解决方案:使用@SqlParser注解
4.2 性能优化建议
- 缓存SQL模板解析结果
- 避免在循环中动态生成SQL
- 使用预编译语句防止重复解析
- 合理设置mybatis-plus.global-config.sql-parser-cache=true
5. 版本升级注意事项
从3.4.x升级到3.5.17需要关注:
- SQL注入器接口变化:
- 新增了方法参数校验
- 修改了抽象方法签名
- 默认方法变更:
- 逻辑删除处理逻辑优化
- 分页查询实现重构
- 配置项调整:
- sqlInjector → global-config.sql-injector
- 移除了部分过时配置
建议升级步骤:
- 备份现有配置
- 逐项测试核心功能
- 特别检查自定义SQL注入器
- 验证分页查询结果
我在实际项目中发现,3.5.17版本对动态表名支持更加完善,通过实现IDynamicTableNameHandler接口可以更灵活地处理分表场景。同时建议在开发环境开启SQL日志,验证生成的SQL是否符合预期。
