试想一下我们的系统,我们所有的表都有五个字段,分别是创建者(create_by)、创建时间(create_time)、修改者(update_by)、修改时间(update_time)、删除标志(del_flag), 同时通过mybatis拦截器,自动注入创建人、创建时间、修改人、修改时间。
目前在数据库新增,能自动注入创建人、创建时间,修改时,能自动注入修改人、 修改时间。如果我们调用mybatis-plus提供的删除方法(deleteById),既然是逻辑删除,我们设想的肯定是此时能够自动注入修改人、修改时间,但是,实际测试你会发现,此时sql并没有注入修改人、修改时间。
为了解决这个问题,mybatis-plus提供了一个LogicDeleteByIdWithFill
的逻辑删除组装件。通过此方法,我们在进行逻辑删除时,便能自动注入修改人、修改时间。
继承DefaultSqlInjector
/**
* Description:官方逻辑删除选装件
*
* @author : laughing
* DateTime: 2021-06-11 15:21
*/
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
//2.官方选装件,逻辑删除时,自动填充其他字段(例如逻辑删除时,自动填充删除人是谁,什么时候删除的)
methodList.add(new LogicDeleteByIdWithFill());
return methodList;
}
}
配置逻辑删除插件
/**
* Mybatis-Plus配置
*
* @author laughing
*/
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {
@javax.annotation.Resource
private Environment env;
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
private final Logger logger = LoggerFactory.getLogger(MyBatisPlusConfig.class);
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
// 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(
new TenantLineHandler() {
// manager_id = 1088248166370832385
// 获取租户 ID 值表达式,只支持单个 ID 值
@Override
public Expression getTenantId() {
return new StringValue(SecurityUtils.getOrgCode());
}
// 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件,
// 这里设置 role表不需要该条件
@Override
public boolean ignoreTable(String tableName) {
logger.info("orgCode=======" + SecurityUtils.getOrgCode());
return StringUtils.isEmpty(SecurityUtils.getOrgCode()) || WisdomAgricultureConfig.getFilterTableList().stream().anyMatch(e -> e.equalsIgnoreCase(tableName));
}
@Override
public String getTenantIdColumn() {
return "org_code";
}
}));
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
public static String setTypeAliasesPackage(String typeAliasesPackage) {
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
List<String> allResult = new ArrayList<String>();
try {
for (String aliasesPackage : typeAliasesPackage.split(",")) {
List<String> result = new ArrayList<String>();
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
Resource[] resources = resolver.getResources(aliasesPackage);
if (resources != null && resources.length > 0) {
MetadataReader metadataReader = null;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
try {
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
if (result.size() > 0) {
HashSet<String> hashResult = new HashSet<String>(result);
allResult.addAll(hashResult);
}
}
if (allResult.size() > 0) {
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
} else {
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
}
} catch (IOException e) {
e.printStackTrace();
}
return typeAliasesPackage;
}
public Resource[] resolveMapperLocations(String[] mapperLocations) {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<Resource>();
if (mapperLocations != null) {
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage");
String mapperLocations = env.getProperty("mybatis-plus.mapperLocations");
String configLocation = env.getProperty("mybatis-plus.configLocation");
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
VFS.addImplClass(SpringBootVFS.class);
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
sessionFactory.setPlugins(mybatisSqlInterceptor(), mybatisPlusInterceptor());
sessionFactory.setGlobalConfig(globalConfig());
return sessionFactory.getObject();
}
@Bean
public MybatisSqlInterceptor mybatisSqlInterceptor() {
MybatisSqlInterceptor mybatisSqlInterceptor = new MybatisSqlInterceptor();
Properties properties = new Properties();
mybatisSqlInterceptor.setProperties(properties);
return mybatisSqlInterceptor;
}
/**
* 逻辑删除插件
*/
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
dbConfig.setLogicDeleteValue("Y");
dbConfig.setLogicNotDeleteValue("N");
globalConfig.setDbConfig(dbConfig);
globalConfig.setSqlInjector(sqlInjector());
return globalConfig;
}
/**
* 自定义Sql注入器
*/
@Bean
public MySqlInjector sqlInjector() {
return new MySqlInjector();
}
}
扩展BaseMapper
/**
* Description:
*
* @author : laughing
* DateTime: 2021-06-11 15:23
*/
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 逻辑删除,并且带自动填充
*/
int deleteByIdWithFill(T entity);
}
修改Mapper接口
修改Mapper
接口,将原来继承BaseMapper
改成我们自定义的MyBaseMapper
/**
* Description:红外测温
*
* @author : laughing
* DateTime: 2021-05-18 10:28
*/
public interface CulturePigTemperatureMapper extends MyBaseMapper<CulturePigTemperature> {
/**
* 红外测温列表查询
* @param pig 查询条件
* @return 结果
*/
List<CulturePigTemperature> selectCulturePigTemperatureList(CulturePig pig);
}
修改删除方法
将原来的删除方法deleteById
改成deleteByIdWithFill
再次测试,可以看到修改人、修改时间字段能够在逻辑删除方法时自动注入。
评论 (0)