sql注入器
public interface ISqlInjector {
/**
* <p>
* 检查SQL是否注入(已经注入过不再注入)
* </p>
*
* @param builderAssistant mapper 信息
* @param mapperClass mapper 接口的 class 对象
*/
void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
}
- AbstractSqlInjector实现了ISqlInjector接口
public abstract class AbstractSqlInjector implements ISqlInjector {
protected final Log logger = LogFactory.getLog(this.getClass());
public AbstractSqlInjector() {
}
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
Class<?> modelClass = ReflectionKit.getSuperClassGenericType(mapperClass, Mapper.class, 0);
if (modelClass != null) {
String className = mapperClass.toString();
Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
if (!mapperRegistryCache.contains(className)) {
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
List<AbstractMethod> methodList = this.getMethodList(mapperClass, tableInfo);
if (CollectionUtils.isNotEmpty(methodList)) {
methodList.forEach((m) -> {
m.inject(builderAssistant, mapperClass, modelClass, tableInfo);
});
} else {
this.logger.debug(mapperClass.toString() + ", No effective injection method was found.");
}
mapperRegistryCache.add(className);
}
}
}
public abstract List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo);
}
- DefaultSqlInjector继承了AbstractSqlInjector抽象类
public class DefaultSqlInjector extends AbstractSqlInjector {
public DefaultSqlInjector() {
}
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
Builder<AbstractMethod> builder = Stream.builder().add(new Insert()).add(new Delete()).add(new DeleteByMap()).add(new Update()).add(new SelectByMap()).add(new SelectCount()).add(new SelectMaps()).add(new SelectMapsPage()).add(new SelectObjs()).add(new SelectList()).add(new SelectPage());
if (tableInfo.havePK()) {
builder.add(new DeleteById()).add(new DeleteBatchByIds()).add(new UpdateById()).add(new SelectById()).add(new SelectBatchByIds());
} else {
this.logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.", tableInfo.getEntityType()));
}
return (List)builder.build().collect(Collectors.toList());
}
}
-
自定义自己的通用方法可以实现接口 ISqlInjector 也可以继承抽象类 AbstractSqlInjector 注入通用方法 SQL 语句 然后继承 BaseMapper 添加自定义方法,全局配置 sqlInjector 注入 MP 会自动将类所有方法注入到 mybatis 容器中
-
例如自定义1个删除全部的通用方法
-
第1步,定义sql
public class DeleteAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
/* 执行 SQL ,动态 SQL 参考类 SqlMethod */
String sql = "delete from " + tableInfo.getTableName();
/* mapper 接口方法名一致 */
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
- 第2步,注册自定义的方法
public class MyLogicSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法,保留MP自带方法
* 可以super.getMethodList() 再add
* @return
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new DeleteAll());
methodList.add(new MyInsertAll());
methodList.add(new MysqlInsertAllBatch());
methodList.add(new SelectById());
return methodList;
}
}
- 第3步,把方法定义到BaseMapper
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 自定义通用方法
*/
Integer deleteAll();
int myInsertAll(T entity);
/**
* 如果要自动填充,@{@code Param}(xx) xx参数名必须是 list/collection/array 3个的其中之一
*
* @param batchList
* @return
*/
int mysqlInsertAllBatch(@Param("list") List<T> batchList);
}
- 测试
@SpringBootTest
class DeluxeTest {
@Resource
private UserMapper mapper;
/**
* 使用自定义的通用方法
* delete from user
*/
@Test
void testDelAll() {
mapper.deleteAll();
}
}