在数据库的使用过程中,经常会遇到用某个数值来表示某种状态、类型或者阶段的情况。
以前我都是使用Integer来表示的,缺点是数值的含义不明确,最好的解决方案是使用枚举来替换整型类型。比如有这样一个枚举:
1 | public enum Sex { |
我们希望将表示性别的值存入数据库,即Sex.MALE
存入数据库的值为1,Sex.FEMALE
存入数据库的值为0
本文参考了
如何在MyBatis中优雅的使用枚举。
Mybatis自带的枚举转换器
Mybatis内置了两个枚举转换器:
- org.apache.ibatis.type.EnumTypeHandler:这是默认的枚举转换器,该转换器将枚举实例转换为实例名称的字符串,即将
Sex.MALE
转换为MALE
org.apache.ibatis.type.EnumOrdinalTypeHandler:这个转换器将枚举实例的ordinal属性作为取值,即
Sex.MALE
转换为0
,Sex.FEMALE
转换为1
使用
EnumOrdinalTypeHandler
的方式是在Mybatis配置文件中定义:1
2
3<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="love.wangqi.domain.enums.Sex"/>
</typeHandlers>
以上两种转换器都不能满足我们的需求,所以要自己编写一个转换器
方案
MyBatis提供了org.apache.ibatis.type.BaseTypeHandler
类用于我们自己扩展类型转换器,上面的EnumTypeHandler
和EnumOrdinalTypeHandkler
也都实现了这个接口。
定义接口
我们需要一个接口来确定某部分枚举类的行为。如下:
1 | public interface BaseCodeEnum { |
该接口只有一个返回编码的方法,返回值将被存入数据库。
改造枚举
1 | public enum Sex implements BaseCodeEnum { |
编写转换工具类
现在我们能顺利的将枚举转换为某个数值了,还需要一个工具将数值转换为枚举实例。
1 | public class CodeEnumUtil { |
自定义类型转换器
1 | public class CodeEnumTypeHandler<E extends Enum<?> & BaseCodeEnum> extends BaseTypeHandler<BaseCodeEnum> { |
使用
接下来需要指定哪个类使用我们自己编写转换器进行转换,在MyBatis配置文件中配置如下:
1 | <typeHandlers> |
经测试Sex.MALE
被转换为1
,Sex.FEMALE
被转换为0
,达到了预期的效果
修改默认枚举转换器
我们在MyBatis中添加typeHandler
用于指定哪些类使用我们自定义的转换器,一旦系统中的枚举类多了起来,MyBatis的配置文件维护起来会变得非常麻烦,也容易出错。我们可以在SqlSessionFactory
创建的过程中指定默认枚举转换器。
首先,我们需要一个能确定转换行为的转换器:
1 | public class AutoEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> { |
接下来,我们在SqlSessionFactory
的创建过程中,指定默认枚举转换器
1 | // 取得类型转换注册器 |
spring boot
如果在spring boot中引入mybatis-spring-boot-starter
包,则不需要手动创建SqlSessionFactory,只需要在配置文件中指定mybatis.default-enum-type-handler=love.wangqi.springbootmybatisdemo.model.enums.typehandler.AutoEnumTypeHandler
mybatis plus
如果使用的是mybatis plus,则需要在配置文件中指定typeHandler所在的包:mybatis-plus.type-handlers-package
。并且不再需要AutoEnumTypeHandler
,mybatis plus会根据枚举类型选择合适的类型转换器。
与前端交互
经过以上处理,我们实现了枚举类型到数据库数据的相互转化。我们还需要使用枚举类型与前端进行交互,这部分详见Jackson枚举类处理