在Mybatis中,处理枚举类的TypeHandler有两个:

  1. EnumTypeHandler: 用于保存枚举名
  2. EnumOrdinalTypeHandler: 用于保存枚举的序号。

在实际项目中,以上往往不能满足我们的需求。

需求分析

枚举需要包含两个属性,label(用于显示), value(实际的枚举值)。数据库保存枚举值(value)。

这很明显Mybatis提供的两个枚举TypeHandler不能满足我们的需求。此时,我们可以自定义一个通用的枚举TypeHandler来满足我们的需求。

自定义枚举TypeHandler

通用枚举DisplayedEnum

public interface DisplayedEnum {

    String DEFAULT_VALUE_NAME = "value";

    String DEFAULT_LABEL_NAME = "label";

    default Integer getValue() {
Field field = ReflectionUtils.findField(this.getClass(), DEFAULT_VALUE_NAME);
if (field == null)
return null;
try {
field.setAccessible(true);
return Integer.parseInt(field.get(this).toString());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} @JsonValue
default String getLabel() {
Field field = ReflectionUtils.findField(this.getClass(), DEFAULT_LABEL_NAME);
if (field == null)
return null;
try {
field.setAccessible(true);
return field.get(this).toString();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} static <T extends Enum<T>> T valueOfEnum(Class<T> enumClass, Integer value) {
if (value == null)
throw new IllegalArgumentException("DisplayedEnum value should not be null");
if (enumClass.isAssignableFrom(DisplayedEnum.class))
throw new IllegalArgumentException("illegal DisplayedEnum type");
T[] enums = enumClass.getEnumConstants();
for (T t: enums) {
DisplayedEnum displayedEnum = (DisplayedEnum)t;
if (displayedEnum.getValue().equals(value))
return (T) displayedEnum;
}
throw new IllegalArgumentException("cannot parse integer: " + value + " to " + enumClass.getName());
}
}

说明:
普通枚举类通过实现DisplayedEnum接口,就可以:

  1. 通过getValue()获取枚举值。
  2. 通过getLabel()获取枚举的label属性。
  3. 通过valueOfEnum()将Integer值转换为指定的枚举类型。

普通枚举类

public enum CommonsType implements DisplayedEnum {

    NORMAL("正常", 0), INVALID("无效", 1);

    String label;

    Integer value;

    private CommonsType(String label, Integer value) {
this.label = label;
this.value = value;
}
}

以上就是一个普通枚举类的示例。

自定义枚举TypeHandler

@MappedJdbcTypes(value = JdbcType.TINYINT, includeNullJdbcType = true)
public class DefaultEnumTypeHandler extends BaseTypeHandler<DisplayedEnum> { private Class<DisplayedEnum> type; public EnumTypeHandler(){}; public EnumTypeHandler(Class<DisplayedEnum> type) {
if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
this.type = type;
} @Override
public void setNonNullParameter(PreparedStatement ps, int i, DisplayedEnum parameter, JdbcType jdbcType)
throws SQLException {
ps.setInt(i, parameter.getValue());
} @Override
public DisplayedEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
return convert(rs.getInt(columnName));
} @Override
public DisplayedEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return convert(rs.getInt(columnIndex));
} @Override
public DisplayedEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return convert(cs.getInt(columnIndex));
} private DisplayedEnum convert(int status){
DisplayedEnum[] objs = type.getEnumConstants();
for(DisplayedEnum em: objs){
if(em.getValue() == status){
return em;
}
}
return null;
}
}

使用我们自定义的DefaultEnumTypeHandler

由于Mybatis默认在处理枚举类型的时候会使用EnumTypeHandler(只保存及转换枚举类型的名字), 因此,我们需要手动指定使用DefaultEnumTypeHandler。示例如下:

<resultMap id="xxx" type="xxx">
...
<result column="type" jdbcType="TINYINT" property="type" typeHandler="xxx.xxx.xxx.DefaultEnumTypeHandler" />
...
</resultMap>

即我们需要通过使用typeHandler来指定。

小结

以上是我们应用在实际项目中的一个对于Mybatis处理枚举类的方案。我看大多数人也都是这样在用。然而,在实际项目中,我们会发现随着枚举类的增多,这样写起来会很繁琐。我看了一下网络上似乎也没人处理这种情况。那么,下一篇文章将针对这种情况进行处理。

转自:https://javafan.cn/2017/02/16/mybatis_typehandler/

Mybatis之XML使用Enum枚举传递数据的更多相关文章

  1. OpenCV和Matlab 通过XML传递数据

    因为现在下到的数据集大部分都使用了Matlab的Calibration toolbox 进行标定,其结构大部分是.mat结构的,所以它和opencv中数据传递需要一个中间过程,网上也有直接调用matl ...

  2. 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD

    使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...

  3. Mybatis系列全解(四):全网最全!Mybatis配置文件XML全貌详解

    封面:洛小汐 作者:潘潘 做大事和做小事的难度是一样的.两者都会消耗你的时间和精力,所以如果决心做事,就要做大事,要确保你的梦想值得追求,未来的收获可以配得上你的努力. 前言 上一篇文章 <My ...

  4. mybatis Mapper XML 文件

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

  5. MyBatis 的 XML 映射文件使用说明

    简介 文档参考地址:http://www.mybatis.org/mybatis-3/zh/index.html MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器 ...

  6. SpringBoot整合Mybatis之xml

    SpringBoot整合Mybatis mybatis ORM框架.几个重要的概念: Mapper配置 : 可以使用基于XML的Mapper配置文件来实现,也可以使用基于Java注解的Mybatis注 ...

  7. MyBatis——Mapper XML 文件

    Mapper XML 文件 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会 ...

  8. MyBatis Mapper XML 文件 的学习详解

    MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JDBC 代码来比较,你会发现映射文件节省了大约 ...

  9. MyBatis Mapper XML 详解

    MyBatis Mapper XML 详解 MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JD ...

随机推荐

  1. 抽象工厂 C++实现

    抽象工厂(Abstract Factory) 抽象工厂是为了提供一系列相关或相互依赖对象的接口.对象创建型模式的一种. 客户Client 抽象工厂接口AbstractFactory 抽象工厂的实现类C ...

  2. Python3 列表List(十一)

    list是一种有序可重复的集合,可以随时添加和删除其中的元素. 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. ...

  3. 修改Oracle归档日志方法

    修改Oracle归档日志的方法 Oracle默认安装的归档日志只有50M,在做大量操作的时候会经常切换日志文件,造成性能问题,下面是具体操作方法 1. 下面是查看现有归档日志大小:   SQL> ...

  4. word 使用中 上标符号的实现

    1.   首先在word 中打下一段话  如:   啦啦啦啦啦啦啦啦  然后加入你需要的上标   如   [2] 2.    选中你需要的上标,然后右击 3.   点击字体选项 出现下图: 4.  在 ...

  5. Inno Setup 软件封装

    例子: ; 脚本用 Inno Setup 脚本向导 生成. ; 查阅文档获取创建 INNO SETUP 脚本文件的详细资料! #define MyAppName "隧道照明系统客户端程序&q ...

  6. python3 openpyxl基本操作

    #coding:utf-8 import xlrd import xlwt # 读写2007 excel import openpyxl import sys #读取设备sn # def readSN ...

  7. python requests 设置headers 和 post请求体x-www-form-urlencoded

    1.application/json:是JSON格式提交的一种识别方式.在请求头里标示.2.application/x-www-form-urlencoded : 这是form表单提交的时候的表示方式 ...

  8. mysql master master slave 环境搭建

    master1:192.168.128.47 master2:192.168.128.96 slave:192.168.128.97   master1与master2互备,master2作为slav ...

  9. js中setAttribute 的兼容性

    js中setAttribute 的兼容性class和className兼容方法: object.setAttribute("class","content") ...

  10. zipkin对于dubbo的支持

    对于Web端: 1. 需要在applicationContext的头部添加中添加prefix引用: xmlns:dubbo="http://code.alibabatech.com/sche ...