1.需求
在实际需求中,经常会存在实体对象的标签信息,通常这些标签是固定的,我们在Java中用枚举来表示,针对枚举类型在数据库与Java之间的转换,Mybatis plus提供了@EnumValue注解。其实是针对该枚举类型生成了类型处理器。但如果标签允许多选,基础的无法满足,我们就需要自定义类型处理器了。
2. 实现
2.1
首先实现自定义类型处理器,只需要继承Mybatis提供的BaseTypeHandler 类,并实现其类型处理方法。
2.2
第二步是将实体类与类型转换器关联起来,Plus通过注解实现,有两步:
-
实体类上标记注解@TableName(autoResultMap=true) 开启自动填充ResultMap。
-
属性上通过@TableField(typeHandler = xxx.class)指定类型处理器。
3. 示例
3.1 相关类
标签枚举
实体类(因为是多标签,这里用List封装枚举)
Service
Mapper
3.2 自定义类型处理器
继承BaseTypeHandler类
实现处理方法(可以根据需求定制转换规则,这里我直接用JSON处理了。)
3.3 在实体类种配置注解
3.4 演示
3.4.1. 保存实体类
调试运行,查看断点
可以看到处理器拦截到对象并转成了JSON
数据库中保存的为JSON字符串
3.4.2. 查询实体类
调试运行,查看断点,可以看到处理器拦截到了JSON字符串并转成了List集合
4. 注意事项
-
通过注解配置的方式,只对Plus提供的基础方法生效,也就是如果你在Mapper里写了个方法,并且自定义了SQL,是不会生效的。Plus根据扫描实体类注解生成了一个ResultMap并且其Service生成的基础方法都关联引用。这么一来Plus提供的基础方法,都会触发类型转换器。
可以看看原生mapper.xml里配置自定义类型转换器
以上方法只对查询生效
保存时的配置方法
-
关于mybatis-plus.type-handlers-package 开启扫描包中的类型处理器,这里有个坑,mybatis是用java类型作为key保存typeHandler,如果定义了两个相同java类型但不同逻辑的处理器,它只会存一个。并且,它对所有包含该类型的实体类都会生效,除非你指定关联了其他类型处理器。也就是全局通用的。如果不想做全局通用,建议不要开启包扫描。特别是像List这种类型,其实我们更关注的是内部的对象,并且会有不同的处理逻辑。
例如:
可以看到List集合里对象并不相同,可能处理逻辑也不同。但只要你开启了包扫描,并包含List类型的处理器 它们的命中方式是这样的
如果我们是一套逻辑处理所有的List类型,那么自定义一个List类型处理器并开启包扫描即可,如果有不同的处理逻辑,则需要指定类型处理器,否则要么命中全局的,要么找不到处理器抛异常。
以上是笔者结合源码通过测试所得出的结论,如果有理解错误的地方,欢迎指出。