前言
Mybatis-Plus中提供了很多通用方法,可以参见DefaultSqlInjector类,如下:
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());
}
}
我们也可以自定义一些通用方法,定义继承BaseMapper的通用Mapper,实现自己的通用方法。
一、自定义方法枚举
package com.iscas.biz.mp.enhancer.enums;
/**
*
* @author zhuquanwen
* @vesion 1.0
* @date 2021/12/23 14:09
* @since jdk1.8
*/
public enum CustomSqlMethod {
/**
* truncate
* */
TRUNCATE("truncate", "truncate一张表", "<script>\nTRUNCATE TABLE %s \n</script>");
private final String method;
private final String desc;
private final String sql;
CustomSqlMethod(String method, String desc, String sql) {
this.method = method;
this.desc = desc;
this.sql = sql;
}
public String getMethod() {
return method;
}
public String getDesc() {
return desc;
}
public String getSql() {
return sql;
}
}
二、自定义方法
package com.iscas.biz.mp.enhancer.injector.methods;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.iscas.biz.mp.enhancer.enums.CustomSqlMethod;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* truncate表
*
* @author zhuquanwen
* @vesion 1.0
* @date 2021/12/23 13:57
* @since jdk1.8
*/
public class TruncateMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
CustomSqlMethod sqlMethod = CustomSqlMethod.TRUNCATE;
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
}
}
三、自定义SQL注入器
package com.iscas.biz.mp.enhancer.injector;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.iscas.common.tools.core.io.file.ScannerUtils;
import com.iscas.common.tools.exception.lambda.Lambdas;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义SQL注入器
*
* @author zhuquanwen
* @vesion 1.0
* @date 2021/12/23 14:18
* @since jdk1.8
*/
@Component
public class CustomSqlInjector extends DefaultSqlInjector {
private volatile List<AbstractMethod> methodCache;
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
if (methodCache == null) {
synchronized (CustomSqlInjector.class) {
if (methodCache == null) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.addAll(getCustomMethods());
methodCache = methodList;
}
}
}
return methodCache;
}
/**
* 获取methods包下的所有方法类,并实例化
*/
private List<? extends AbstractMethod> getCustomMethods() {
String methodsPackageName = CustomSqlInjector.class.getPackageName() + ".methods";
return ScannerUtils.getClasses(methodsPackageName)
.stream().filter(AbstractMethod.class::isAssignableFrom)
.map(Lambdas.wrapperFunction(clazz -> (AbstractMethod) clazz.getDeclaredConstructor().newInstance()))
.collect(Collectors.toList());
}
}
注意的是如果使用的mybatis-plus-boot-starter
依赖,上面这样写就可以了。如果没有使用mybatis-plus的自动配置依赖,需要在SqlSessionFactory中添加GlobalConfig,GlobalConfig中添加Sql注入器。
@Primary
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
//configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
factory.setConfiguration(configuration);
PaginationInnerInterceptor paginationInnerInterceptor = paginationInterceptor();
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(paginationInnerInterceptor);
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
factory.setPlugins(interceptor);
if (StringUtils.isNotBlank(enumPackages)) {
factory.setTypeEnumsPackage(enumPackages);
}
factory.setGlobalConfig(globalConfiguration());
factory.setTransactionFactory(new MultiDataSourceTransactionFactory());
//mapper config path
String mpMapperLocations = environment.getProperty("mp.mapper.locations");
if (StringUtils.isNotEmpty(mpMapperLocations)) {
Arrays.stream(mpMapperLocations.split(","))
.forEach(location -> {
try {
factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(location));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
return factory.getObject();
}
private GlobalConfig globalConfiguration() {
GlobalConfig conf = GlobalConfigUtils.defaults();
conf.getDbConfig().setIdType(IdType.valueOf(idType));
conf.setSqlInjector(new CustomSqlInjector());
return conf;
}
四、自定义通用Mapper
package com.iscas.biz.mp.enhancer.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.iscas.biz.mp.aop.enable.ConditionalOnMybatis;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* 执行SQL语句的Mapper
*
* @author zhuquanwen
* @vesion 1.0
* @date 2018/9/27 10:23
* @since jdk1.8
*/
@Repository
@ConditionalOnMybatis
public interface DynamicMapper<T> extends BaseMapper<T> {
/**
* 扩展Mybatis-Plus的方法
* truncate
* */
void truncate();
}
五、测试
package com.iscas.biz.mp.test.model;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
/**
* @author zhuquanwen
* @vesion 1.0
* @date 2020/3/26 13:46
* @since jdk1.8
*/
@Data
public class Test {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Integer age;
}
package com.iscas.biz.mp.test.mapper;
import com.iscas.biz.mp.enhancer.mapper.DynamicMapper;
import com.iscas.biz.mp.test.model.Test;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
*
* @author zhuquanwen
* @vesion 1.0
* @date 2020/3/26 14:08
* @since jdk1.8
*/
@Repository
@Mapper
public interface TestMapper extends DynamicMapper<Test> {
}
/**
* @author zhuquanwen
* @vesion 1.0
* @date 2020/3/26 14:09
* @since jdk1.8
*/
@RestController
@RequestMapping("/test/mybatis/plus")
@ConditionalOnMybatis
public class TestController extends BaseController {
@Autowired
private TestMapper testMapper;
@GetMapping("/truncate")
public ResponseEntity testTruncate() {
testMapper.truncate();
return getResponse();
}
}