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 相关类
标签枚举
![](https://img-blog.csdnimg.cn/img_convert/9ed639e2e41b52bbd8ffebed456edccd.png)
实体类(因为是多标签,这里用List封装枚举)
![](https://img-blog.csdnimg.cn/img_convert/b080b0d60c5f67ea27d78b416d4097b4.png)
Service
![](https://img-blog.csdnimg.cn/img_convert/aa277aee03033bcae51dbf087e25e029.png)
![](https://img-blog.csdnimg.cn/img_convert/8d3b4bb77a7f400efb85529ce45130e7.png)
Mapper
![](https://img-blog.csdnimg.cn/img_convert/36c6367a13a9782c5230cb9485dc6034.png)
3.2 自定义类型处理器
继承BaseTypeHandler类
![](https://img-blog.csdnimg.cn/img_convert/b94d02a211d48e49f20fedddc4e1134e.png)
实现处理方法(可以根据需求定制转换规则,这里我直接用JSON处理了。)
![](https://img-blog.csdnimg.cn/img_convert/87ddf1c68ec4225ecacf2f95f5eef8bd.png)
![](https://img-blog.csdnimg.cn/img_convert/846aa80dab9064cdbe5c1d2781bd3dfb.png)
3.3 在实体类种配置注解
![](https://img-blog.csdnimg.cn/img_convert/109642e86a99574438b3b3f1c1a89042.png)
3.4 演示
3.4.1. 保存实体类
![](https://img-blog.csdnimg.cn/img_convert/5182ec88412ebe250db7f50c00524de9.png)
调试运行,查看断点
![](https://img-blog.csdnimg.cn/img_convert/205c1fdea1a2eb6e0bdd596ae70eba4a.png)
可以看到处理器拦截到对象并转成了JSON
![](https://img-blog.csdnimg.cn/img_convert/a96d2a37eded4b38b8e5c10acd821c18.png)
数据库中保存的为JSON字符串
![](https://img-blog.csdnimg.cn/img_convert/b1e2c75d692355aeec5047c245225c35.png)
3.4.2. 查询实体类
![](https://img-blog.csdnimg.cn/img_convert/ccf4aa423d081296e3bd829ba7807095.png)
调试运行,查看断点,可以看到处理器拦截到了JSON字符串并转成了List集合
![](https://img-blog.csdnimg.cn/img_convert/1c54fbd3ad2ac87c7019f399e6819435.png)
4. 注意事项
-
通过注解配置的方式,只对Plus提供的基础方法生效,也就是如果你在Mapper里写了个方法,并且自定义了SQL,是不会生效的。Plus根据扫描实体类注解生成了一个ResultMap并且其Service生成的基础方法都关联引用。这么一来Plus提供的基础方法,都会触发类型转换器。
可以看看原生mapper.xml里配置自定义类型转换器
![](https://img-blog.csdnimg.cn/img_convert/153b4961f07fcefeb6e0785bdcd3ca12.png)
以上方法只对查询生效
保存时的配置方法
![](https://img-blog.csdnimg.cn/img_convert/df4ad6fab44cd676d8630e9df91cf99b.png)
-
关于mybatis-plus.type-handlers-package 开启扫描包中的类型处理器,这里有个坑,mybatis是用java类型作为key保存typeHandler,如果定义了两个相同java类型但不同逻辑的处理器,它只会存一个。并且,它对所有包含该类型的实体类都会生效,除非你指定关联了其他类型处理器。也就是全局通用的。如果不想做全局通用,建议不要开启包扫描。特别是像List这种类型,其实我们更关注的是内部的对象,并且会有不同的处理逻辑。
例如:
![](https://img-blog.csdnimg.cn/img_convert/31988fce843954d3e1206ade39202885.png)
可以看到List集合里对象并不相同,可能处理逻辑也不同。但只要你开启了包扫描,并包含List类型的处理器 它们的命中方式是这样的
![](https://img-blog.csdnimg.cn/img_convert/23f1415bb102aa890f7f02c36be914b9.png)
如果我们是一套逻辑处理所有的List类型,那么自定义一个List类型处理器并开启包扫描即可,如果有不同的处理逻辑,则需要指定类型处理器,否则要么命中全局的,要么找不到处理器抛异常。
![](https://img-blog.csdnimg.cn/img_convert/eb4a4a6f274ebff026d85d7d9b052ca9.png)
以上是笔者结合源码通过测试所得出的结论,如果有理解错误的地方,欢迎指出。