mybatisplusSQL注入器详解
一、什么是SQL注入器?
我们在使用mybatis-plus的时候,dao层都会继承BaseMapper接口,这样就可以使用BaseMapper接口的所有方法,BaseMapper接口的每一个方法其实就是一个SQL注入器。
在Mybatis-Plus的核心(core)的injector.methods包下,提供的很多注入方法。
二、自带的SQL注入器
在Mybatis-Plus(extension)的injector.methods包下有四个可拓展的注入方法。
AlwaysUpdateSomeColumnById:根据id更新字段(全量更新不忽略null字段),updateById默认会自动忽略实体类中null值字段
InsertBatchSomeColumn:真实批量插入,saveBatch其实是伪批量插入
LogicDeleteByIdWithFill:逻辑删除增加填充功能,比如删除的时候填充更新时间、更新人
Upsert:插入一条数据,选择字段插入
三、测试自带的SQL注入器
1.SQL注入器全局配置
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author wjj
*/
@Component
public class MySqlInjector extends DefaultSqlInjector {
public MySqlInjector() {
super();
}
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methods = super.getMethodList(mapperClass);
methods.add(new InsertBatchSomeColumn(i-> i.getFieldFill() != FieldFill.UPDATE));
methods.add(new AlwaysUpdateSomeColumnById(i-> i.getFieldFill() != FieldFill.INSERT));
return methods;
}
}
2.自定义MyBaseMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MyBaseMapper<T> extends BaseMapper<T> {
int alwaysUpdateSomeColumnById(@Param("et")T entity);
int insertBatchSomeColumn(List<T> entityList);
}
3.实体类mapper继承MyBaseMapper
public interface UserMapper extends MyBaseMapper<UserPO> {
}
4.测试
略
四、自定义Sql注入器
1.创建一个方法FindList继承mybatisplus的AbstractMethod
书写一个非逻辑删除查询所有的方法(其他同理)
参考Mybatis-Plus的核心(core)的injector.methods包下的selectList方法
import com.baomidou.mybatisplus.core.enums.SqlMethod;
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;
public class FindList extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.SELECT_LIST;
String sql = String.format(sqlMethod.getSql(), this.sqlFirst(), this.sqlSelectColumns(tableInfo, true), tableInfo.getTableName(), this.sqlWhereEntityWrapper(true, tableInfo), this.sqlComment());
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addSelectMappedStatementForTable(mapperClass, "finList", sqlSource, tableInfo);
}
@Override
protected String sqlWhereEntityWrapper(boolean newLine, TableInfo table) {
String sqlScript;
sqlScript = table.getAllSqlWhere(false, true, "ew.entity.");
sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", "ew.entity"), true);
sqlScript = sqlScript + "\n";
sqlScript = sqlScript + SqlScriptUtils.convertIf(String.format(SqlScriptUtils.convertIf(" AND", String.format("%s and %s", "ew.nonEmptyOfEntity", "ew.nonEmptyOfNormal"), false) + " ${%s}", "ew.sqlSegment"), String.format("%s != null and %s != '' and %s", "ew.sqlSegment", "ew.sqlSegment", "ew.nonEmptyOfWhere"), true);
sqlScript = SqlScriptUtils.convertWhere(sqlScript) + "\n";
sqlScript = sqlScript + SqlScriptUtils.convertIf(String.format(" ${%s}", "ew.sqlSegment"), String.format("%s != null and %s != '' and %s", "ew.sqlSegment", "ew.sqlSegment", "ew.emptyOfWhere"), true);
sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", "ew"), true);
return newLine ? "\n" + sqlScript : sqlScript;
}
}
2.在MyBaseMapper添加方法
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MyBaseMapper<T> extends BaseMapper<T> {
int alwaysUpdateSomeColumnById(@Param("et")T entity);
int insertBatchSomeColumn(List<T> entityList);
List<T> finList();
}
3.SQL注入器全局配置
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class MySqlInjector extends DefaultSqlInjector {
public MySqlInjector() {
super();
}
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methods = super.getMethodList(mapperClass);
methods.add(new InsertBatchSomeColumn(i-> i.getFieldFill() != FieldFill.UPDATE));
methods.add(new AlwaysUpdateSomeColumnById(i-> i.getFieldFill() != FieldFill.INSERT));
methods.add(new FindList());
return methods;
}
}
4.测试
略
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix