MyBatis-Plus 编程方式配置扫描通用枚举
2021/5/22 1:55:51
本文主要是介绍MyBatis-Plus 编程方式配置扫描通用枚举,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
使用Mybatis-Plus的通用枚举功能(https://mp.baomidou.com/guide/enum.html)确实可以很优雅的方式将数据库字段直接映射到我们自定义的枚举类,美中不足的是,官方对于自定义枚举类必须要通过属性配置的方式来扫描枚举类的包路径,在一些非直接发布成Spring Application的场景下,就不够用了。
解决思路
通过查找源代码,mybatis-plus.typeEnumsPackage
的这个配置是直接反应到com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties
这个类里面的,可以对注入到Spring容器中的MybatisPlusProperties重新进行值的设置:
@Configuraton public class TypeEnumsPackageConfiguration { @AutoWried MybatisPlusProperties mybatisPlusProperties; @PostConstruct public void configTypeEnumsPackage() { mybatisPlusProperties.setTypeEnumsPackage(String.join(";", properties.getTypeEnumsPackage(), "my.package.type.enums")); } }
解决方法
上面的解决思路试过,确实可以成功,但是不够“优雅”,再看源代码,发现官方提供了com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer
来进行MybatisPlusProperties的自定义设置,其实只要创建一个它的子类,就可以在通过实现customize()方法来自定义配置信息了,那既然要强调“优雅”,并且考虑多模块的复用,可以针对TypeEnumsPackage的设定专门做一个抽象类,在子类中只配置扫描路径的方式来完成。
EnumTypePackageScanner.java
public abstract class EnumTypePackageScanner implements MybatisPlusPropertiesCustomizer { @Override public void customize(MybatisPlusProperties properties) { properties.setTypeEnumsPackage(String.join(";", properties.getTypeEnumsPackage(), this.getTypeEnumsPackage())); } protected abstract String getTypeEnumsPackage(); }
EnumTypePackageScannerConfiguration.java (可在不同模块中分别配置)
@Configuration public class EnumTypePackageScannerConfiguration { @Bean public EnumTypePackageScanner configEnumPackage() { return new EnumTypePackageScanner() { @Override protected String getTypeEnumsPackage() { return "my.package.type.enums"; } }; } }
后续
虽然最终满足了需求,其实还是有些许不甘,同样是包扫描,为什么不提供一个类似于@MapperScan
的注解来指定呢,而且自定义枚举必须要实现Mybatis自有的一些接口或者注解,这个自定义枚举类提到api接口层的话,强行把Mybatis-plus的依赖也会加到api层,虽说最新的版本以及进行了优化,只需引入mybatis-plus-annotation
依赖即可,但是有洁癖的人应该受不了吧。
所以接下来准备自定义一个注解,来指定枚举类扫描,并且要做一个com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
的派生类,主要是要覆盖这段逻辑:
/** * 查找标记标记EnumValue字段 * * @param clazz class * @return EnumValue字段 * @since 3.3.1 */ public static Optional<String> findEnumValueFieldName(Class<?> clazz) { if (clazz != null && clazz.isEnum()) { String className = clazz.getName(); return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> { Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields()) .filter(field -> field.isAnnotationPresent(EnumValue.class)) .findFirst(); return optional.map(Field::getName).orElse(null); })); } return Optional.empty(); }
以及参照com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean
注册MybatisEnumTypeHandler的逻辑,实现自定义注解与自定义EnumTypeHandler的绑定:
if (hasLength(this.typeEnumsPackage)) { Set<Class<?>> classes; if (typeEnumsPackage.contains(StringPool.STAR) && !typeEnumsPackage.contains(StringPool.COMMA) && !typeEnumsPackage.contains(StringPool.SEMICOLON)) { classes = scanClasses(typeEnumsPackage, null); if (classes.isEmpty()) { LOGGER.warn(() -> "Can't find class in '[" + typeEnumsPackage + "]' package. Please check your configuration."); } } else { classes = new HashSet<>(); String[] typeEnumsPackageArray = tokenizeToStringArray(this.typeEnumsPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Assert.notNull(typeEnumsPackageArray, "not find typeEnumsPackage:" + typeEnumsPackage); Stream.of(typeEnumsPackageArray).forEach(typePackage -> { try { Set<Class<?>> scanTypePackage = scanClasses(typePackage, null); if (scanTypePackage.isEmpty()) { LOGGER.warn(() -> "Can't find class in '[" + typePackage + "]' package. Please check your configuration."); } else { classes.addAll(scanTypePackage); } } catch (IOException e) { throw new MybatisPlusException("Cannot scan class in '[" + typePackage + "]' package", e); } }); } // 取得类型转换注册器 TypeHandlerRegistry typeHandlerRegistry = targetConfiguration.getTypeHandlerRegistry(); classes.stream() .filter(Class::isEnum) .filter(MybatisEnumTypeHandler::isMpEnums) .forEach(cls -> typeHandlerRegistry.register(cls, MybatisEnumTypeHandler.class)); }
这篇关于MyBatis-Plus 编程方式配置扫描通用枚举的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求
- 2024-10-01使用 golang 将ETH账户的资产平均分散到其他账户
- 2024-10-01JWT用户校验课程:从入门到实践
- 2024-10-01Server Component课程入门指南