一、ISqlInjector
自动注入器接口
通过实现MyBatisPlus的ISqlInjector
接口可以自定义各种sql,注入到全局中,相当于自定义的MyBatisPlus自动注入的方法。之前需要在xml中进行配置的sql语句,现在通过扩展ISqlInjector
接口在加载MyBatis环境时就注入。
DefaultSqlInjector
是默认SQL注入器,它继承了AbstractSqlInjector
,如果想要扩展SQL注入器,可以通过继承DefaultSqlInjector
来实现
/**
* SQL 默认注入器
*
* @author hubin
* @since 2018-04-10
*/
public class DefaultSqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
return Stream.of(
new Insert(),
new Delete(),
new DeleteByMap(),
new DeleteById(),
new DeleteBatchByIds(),
new Update(),
new UpdateById(),
new SelectById(),
new SelectBatchByIds(),
new SelectByMap(),
new SelectOne(),
new SelectCount(),
new SelectMaps(),
new SelectMapsPage(),
new SelectObjs(),
new SelectList(),
new SelectPage()
).collect(toList());
}
}
AbstractSqlInjector
类实现了ISqlInjector
接口
/**
* SQL 自动注入器
*
* @author hubin
* @since 2018-04-07
*/
public abstract class AbstractSqlInjector implements ISqlInjector {
private static final Log logger = LogFactory.getLog(AbstractSqlInjector.class);
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
Class<?> modelClass = extractModelClass(mapperClass);
if (modelClass != null) {
String className = mapperClass.toString();
Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
if (!mapperRegistryCache.contains(className)) {
List<AbstractMethod> methodList = this.getMethodList(mapperClass);
if (CollectionUtils.isNotEmpty(methodList)) {
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
// 循环注入自定义方法
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
} else {
logger.debug(mapperClass.toString() + ", No effective injection method was found.");
}
mapperRegistryCache.add(className);
}
}
}
/**
* <p>
* 获取 注入的方法
* </p>
*
* @param mapperClass 当前mapper
* @return 注入的方法集合
* @since 3.1.2 add mapperClass
*/
public abstract List<AbstractMethod> getMethodList(Class<?> mapperClass);
/**
* 提取泛型模型,多泛型的时候请将泛型T放在第一位
*
* @param mapperClass mapper 接口
* @return mapper 泛型
*/
protected Class<?> extractModelClass(Class<?> mapperClass) {
Type[] types = mapperClass.getGenericInterfaces();
ParameterizedType target = null;
for (Type type : types) {
if (type instanceof ParameterizedType) {
Type[] typeArray = ((ParameterizedType) type).getActualTypeArguments();
if (ArrayUtils.isNotEmpty(typeArray)) {
for (Type t : typeArray) {
if (t instanceof TypeVariable || t instanceof WildcardType) {
break;
} else {
target = (ParameterizedType) type;
break;
}
}
}
break;
}
}
return target == null ? null : (Class<?>) target.getActualTypeArguments()[0];
}
}
二、自定义SQL注入器
创建一个类,将方法和sql做映射
public class MysqlDeleteAll extends AbstractMethod{
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql = "delete from " + tableInfo.getTableName();
String methodName = "deleteAll";
// 进行预编译得到sqlSource对象
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql,modelClass);
//添加到delete操作的Statement中也就是相当于将预编译sql和其它的delete相关的编译后的sql存在一起
//将EmployeeMapper中定义的deleteAll处理成对应的MapperedStatement对象,加入到configuration对象中
return addDeleteMappedStatement(mapperClass, methodName,sqlSource);
}
}
创建自定义的注入器,继承DefaultSqlInjector
,将sql与方法绑定的实例交给Spring来管理
/**
* 自定义SQL注入器
*/
public class MySqlInjector extends DefaultSqlInjector{
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
/* 如果只需增加方法,保留MP自带方法
* 可以super.getMethodList() 再add
*
* */
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new MysqlDeleteAll());
return methodList;
}
}
将自定义方法名添加到继承了BaseMapper
的EmployeeMapper
中
/**
* <p>
* Mapper 接口
* </p>
*
* @author Jian
* @since 2021-05-21
*/
public interface EmployeeMapper extends BaseMapper<Employee> {
public int deleteAll();
}
将自定义注入器注册到Spring容器中,并且将自定义的SQL注入器注册到全局策略配置
<!--定义MyBatisPlus全局策略配置-->
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<!--实现属性名与数据库表的列名的映射-->
<property name="tableUnderline" value="true"></property>
<!--全局的主键策略-->
<property name="idType" value="AUTO"></property>
<!--全局的表前缀策略配置-->
<property name="tablePrefix" value="tbl_"></property>
</bean>
</property>
<!--将自定义的SQL注入器注册到全局-->
<property name="sqlInjector" ref="mySqlInjector"></property>
</bean>
<!--定义自定义的注入器bean-->
<bean id="mySqlInjector" class="mpGenerator.injector.MySqlInjector"></bean>
测试自定义注入器的deleteAll
方法
@Test
public void testDeleteAll(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = context.getBean("employeeMapper",EmployeeMapper.class);
int result = employeeMapper.deleteAll();
System.out.println("result: " + result);
}
打印日志: