转载

mybatis-plus是如何只做增强不做改变之通用枚举篇

mybatis-plus是如何只做增强不做改变之通用枚举篇

介绍

首先,让我们来看张高清无码图,左边两个是mybatis原生的,右边的两个是mybatis-plus的.

  • EnumTypeHandler( mybatis包 ) : VARCHAR -任何兼容的字符串类型,存储枚举的名称
  • EnumOrdinalTypeHandler: 任何兼容的 NUMERICDOUBLE 类型,存储枚举的索引
  • EnumAnnotationTypeHandler: 处理自定义枚举属性转换器( 注解方式 ) 枚举类需要标记@EnumValue注解
  • EnumTypeHandler( mybatis-plus包 ): 自定义枚举属性转换器( 非注解方式 ) 枚举类需要实现IEnum接口.

如何配置

  1. mybatis原生配置方式:

    mybatis-plus是如何只做增强不做改变之通用枚举篇
    在mybatis配置中,有一项defaultEnumTypeHandler默认枚举配置,默认使用的EnumTypeHandler( mybatis包

    )

  2. mybatis-plus配置方式: 参考下官方使用文档吧,比较简单,划个重点( typeEnumsPackage配置 ) 通用枚举使用

源码解读

//MybatisSqlSessionFactoryBean#buildSqlSessionFactory
//判断是否配置了枚举包扫描
if (hasLength(this.typeEnumsPackage)) {		
            Set<Class> classes;
    		// 扫描包下的class,这里可以看出支持多个包配置.用,或;进行分隔
            if (typeEnumsPackage.contains(StringPool.STAR) && !typeEnumsPackage.contains(StringPool.COMMA)
                && !typeEnumsPackage.contains(StringPool.SEMICOLON)) {
                // 配置包含*且不包含,和;
                classes = PackageHelper.scanTypePackage(typeEnumsPackage);
                if (classes.isEmpty()) {
                    LOGGER.warn(() -> "Can't find class in '[" + typeEnumsPackage + "]' package. Please check your configuration.");
                }
            } else {
                //按,;进行包配置切割
                String[] typeEnumsPackageArray = tokenizeToStringArray(this.typeEnumsPackage,
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
                Assert.notNull(typeEnumsPackageArray, "not find typeEnumsPackage:" + typeEnumsPackage);
                classes = new HashSet<>();
                //循环处理包下的class扫描
                for (String typePackage : typeEnumsPackageArray) {
                    Set<Class> scanTypePackage = PackageHelper.scanTypePackage(typePackage);
                    if (scanTypePackage.isEmpty()) {
                        LOGGER.warn(() -> "Can't find class in '[" + typePackage + "]' package. Please check your configuration.");
                    } else {
                        classes.addAll(PackageHelper.scanTypePackage(typePackage));
                    }
                }
            }
            // 取得类型转换注册器
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            classes.forEach(cls ->{
                //判断当前类是不是枚举类,因为在同个包下,有可能不是枚举,所以跳过非枚举类
                if (cls.isEnum()) {	
                    //判断当前枚举类是不是实现类IEnum接口
                    if (IEnum.class.isAssignableFrom(cls)) {
                        // 注册上当前类的枚举处理器为EnumTypeHandler
                        typeHandlerRegistry.register(cls, EnumTypeHandler.class);
                    } else {
                        // 非IEnum实现类,反射字段遍历,获取第一个@EnumValue字段
                        Optional<Field> optional = dealEnumType(cls);
                        if (optional.isPresent()) {
                            Field field = optional.get();
                            field.setAccessible(true);
                            //缓存下当前类对应的字段----再次划个重点
                            EnumAnnotationTypeHandler.addEnumType(cls, field);
                            //注册上当前类的枚举处理器为EnumAnnotationTypeHandler
                            typeHandlerRegistry.register(cls, EnumAnnotationTypeHandler.class);
                        }
                        //这里找不到了的话就会使用默认的mybatis枚举处理器了(配置方式参考后面).
                    }
                }
            });
        }
//寻找类第一个标记@EnumValue的字段
protected Optional<Field> dealEnumType(Class<?> clazz) {
        return clazz.isEnum() ? Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst() : Optional.empty();
    }
复制代码

总结

mybatis-plus通过 typeEnumsPackage 这属性,来进行枚举类扫描并注册上对应的枚举处理器,在未配置枚举包扫描时或枚举不符合mybaits-plus的注册条件(实现 IEnum 接口或注解 @EnumValue 字段),一律走原生mybatis枚举处理,这项配置可通过设置mybatis的 defaultEnumTypeHandler 来指定.

小提示

最好不要将默认枚举类型处理器指定为mybatis-plus的 EnumAnnotationTypeHandler ,因为这个类在扫描的时候进行了字段的缓存,如果直接将默认枚举处理器指定它,是无法使用的.

指定默认枚举处理器方式

//javaconfig
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultEnumTypeHandler(EnumOrdinalTypeHandler.class); 
复制代码
#yaml
mybatis-plus:
  configuration:
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
复制代码
<!--xml-->
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
复制代码
原文  https://juejin.im/post/5c4d96c1518825254c31c3e4
正文到此结束
Loading...