mybatis处理枚举类的简单方法
作者:疯狂小兵 发布时间:2022-05-22 09:08:20
mybatis自带对枚举的处理类
org.apache.ibatis.type.EnumOrdinalTypeHandler<E>
:该类实现了枚举类型和Integer类型的相互转换。
但是给转换仅仅是将对应的枚举转换为其索引位置,也就是"ordinal()"方法获取到的值。对应自定义的int值,该类无能为力。
org.apache.ibatis.type.EnumTypeHandler<E>
:该类实现了枚举类型和String类型的相互转换。
对于想将枚举在数据库中存储为对应的int值的情况,该类没办法实现。
基于以上mybatis提供的两个枚举处理类的能力有限,因此只能自己定义对枚举的转换了。
自定义mybatis的枚举处理类EnumValueTypeHandler
该类需要继承org.apache.ibatis.type.BaseTypeHandler<E>
,然后在重定义的方法中实现自有逻辑。
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
/**
* 处理实现了{@link EsnBaseEnum}接口的枚举类
* @author followtry
* @time 2016年8月16日 下午8:06:49
* @since 2016年8月16日 下午8:06:49
*/
//在 xml 中添加该 TypeHandler 时需要使用该注解
@MappedTypes(value = {
QcListTypeEnum.class,
SellingQcBizTypeEnum.class
})
public class EnumValueTypeHandler<E extends EsnBaseEnum> extends BaseTypeHandler<E> {
private Class<E> type;
private final E[] enums;
public EnumValueTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
this.enums = type.getEnumConstants();
if (this.enums == null) {
throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
//获取非空的枚举的int值并设置到statement中
ps.setInt(i, parameter.getValue());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int i = rs.getInt(columnName);
if (rs.wasNull()) {
return null;
} else {
try {
return getEnumByValue(i);
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
/**
* 通过枚举类型的int值,获取到对应的枚举类型
* @author jingzz
* @param i
*/
protected E getEnumByValue(int i) {
for (E e : enums) {
if (e.getValue() == i) {
return e;
}
}
return null;
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int i = rs.getInt(columnIndex);
if (rs.wasNull()) {
return null;
} else {
try {
return getEnumByValue(i);
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int i = cs.getInt(columnIndex);
if (cs.wasNull()) {
return null;
} else {
try {
return getEnumByValue(i);
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
}
该处理器是处理继承了EsnBaseEnum接口的枚举类,因为该接口中定义了获取自定义int值的方法。
如果在 mybatis 的 xml 中配置 该 typehandler,则需要添加注解@MappedTypes。在添加 typeHandler 注册时使用具体的实现类注册。
配置文件如下:
<typeAliases>
<!-- 为自定义的 TypeHandler 指定别名,在 sql 的 xml 中即可使用别名访问了 -->
<typeAlias type="cn.followtry.mybatis.EnumValueTypeHandler" alias="enumValueTypeHandler"/>
</typeAliases>
<typeHandlers>
<!--处理枚举的值转换-->
<typeHandler handler="cn.followtry.mybatis.EnumValueTypeHandler"/>
</typeHandlers>
自定义的 Enum 需要实现的接口
/**
* @author jingzz
* @time 2016年8月17日 上午9:22:46
* @since 2016年8月17日 上午9:22:46
*/
public interface EsnBaseEnum {
public int getValue();
}
而实现了EsnBaseEnum的枚举示例如下:
/**
* 同步的类型
* @author jingzz
* @time 2016年8月3日 上午11:13:06
*/
public enum SyncType implements EsnBaseEnum {
DEPT(3),//部门
PERSON(1);//人员
private int value;
private SyncType(int value) {
this.value = value;
}
@Override
public int getValue(){
return this.value;
}
}
只有在实现了EsnBaseEnum的接口,EnumValueTypeHandler才能通过接口的getValue方法获取到对应枚举的值。
到此,对于枚举的简单处理逻辑已经实现完成了,接下来就是如何配置来使用该自定义枚举处理逻辑
配置对枚举的处理
首先,mybatis中对于处理逻辑的设置是在sql的映射文件中,如EsnSyncLogMapper.xml。
关键的设置枚举处理的位置如下:
<resultMap id="BaseResultMap" type="com.test.dao.model.EsnSyncLog" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="sync_time" property="syncTime" jdbcType="TIMESTAMP" />
<result column="total_num" property="totalNum" jdbcType="INTEGER" />
<result column="success_total_num" property="successTotalNum" jdbcType="INTEGER" />
<result column="type" property="type" typeHandler="com.test.common.EnumValueTypeHandler" />
<result column="msg" property="msg" jdbcType="VARCHAR" />
</resultMap>
其中type列设置了属性typeHandler,其值为自定义的枚举处理逻辑。
而在具体sql中也需要使用typeHandler属性,如:
<if test="type != null" >
#{type, typeHandler=com.test.common.EnumValueTypeHandler},
</if>
在mybatis处理到该位置时,就会调用typeHandler指定的处理类来处理枚举类型。
来源:https://segmentfault.com/a/1190000019168232


猜你喜欢
- 什么是Run Dashboard当springcloud的服务有多个时,管理多个服务的启动使用run会不好管理,这样我们就可以使用Run D
- 本文提供了基于MD5加密16位和32位的方法,具体内容如下import java.io.IOException;import java.ma
- 前言在面对 生产者-消费者 的场景下, netcore 提供了一个新的命名空间 System.Threading.Channels 来帮助我
- 前言我们大多数在两种情况下可以看到悬浮窗,一个是视频通话时的悬浮窗,另一个是360卫士的悬浮球,实现此功能的方式比较多,这里以视频通话悬浮窗
- 前言在写项目的时候经常需要特定的时间做一些特定的操作,尤其是游戏服务器,维护线程之类的,这时候就需要用到定时器。如果此时你刚好用的是spri
- 本文实例为大家分享了Android实现画板的具体代码,采用的技术是双缓冲技术,供大家参考,具体内容如下1.双缓冲技术的概念所谓的双缓冲技术其
- 1.狂妄的WPF相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API。例如:WinForm(带控件表单)、GDI+(
- 创建两个场景同时赋值StaticVarious 脚本 然后按键好,H ,J 进行不断切换场景,会发现unity 控制台输出数字不断增加,然后
- 存储的可选项Android 的文件系统类似于其他平台的基于磁盘的文件系统。包括以下几种存储类别:App 私有的存储空间共享的存储空间Pref
- 前言 需要实现环(圆)形菜单。效果预览(更多效果请下载源码体验):实现代码1.CircularMenuItemCustomCont
- 本文实例为大家分享了Android实现简易计算功能的具体代码,供大家参考,具体内容如下效果如图:activity_main.xml<?
- 1. 自动化装配介绍Spring Boot针对mvc做了大量封装,简化开发者的使用,内部是如何管理资源配置,Bean配置,环境变量配置以及启
- 首先说明这是我一个不熟悉idea和SSM框架的新手小白遇到的坑,适合用idea搭建SSM框架的小伙伴看一看,老鸟就不用看了。以下为详细步骤(
- 本文实例为大家分享了WheelPicker自定义时间选择器控件的具体代码,供大家参考,具体内容如下先上图:使用android自带的DateP
- 日常的开发中经常会需要用到自定义View,这次刚好有个需求,需要用到带有节点的进度条。东西很简单直接继承View就行了。首先定义一些需要的属
- 前言安卓的Material库提供了许多样式更精美的控件,其中就有悬浮控件,它表现出一种悬浮在页面的效果,也就是有立体效果的,让人产生这种控件
- refresh()该方法是 Spring Bean 加载的核心,它是 ClassPathXmlApplicationContext 的父类
- 前言本文主要介绍JWT的实战运用。准备工作首先我们创建一个Asp.Net的,包含MVC和WebApi的Web项目。然后使用Nuget搜索JW
- 本文实例讲述了C#实现带百分比的进度条功能。分享给大家供大家参考,具体如下:功能需求:如果程序中会执行一个耗时的计算过程,我想在用户点击按钮
- 前言我们可能听过C语言中的传值和传指针,在其他语言中,也有传引用一说,那么他们到底有什么区别呢?如果你还不能准确地分辨,就该好好了解一下了。