Mybatis枚舉類型轉(zhuǎn)換源碼分析
Mybatis枚舉類型轉(zhuǎn)換
類型轉(zhuǎn)換器源碼分析
在Mybatis的TypeHandlerRegistry中,添加了常用的類轉(zhuǎn)換器,其中默認(rèn)的枚舉類型轉(zhuǎn)換器是EnumTypeHandler。
public final class TypeHandlerRegistry {
....
public TypeHandlerRegistry(Configuration configuration) {
this.unknownTypeHandler = new UnknownTypeHandler(configuration);
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());
...EnumTypeHandler.java,默認(rèn)使用的是枚舉的名稱設(shè)置參數(shù)和轉(zhuǎn)換枚舉類型。
public EnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, parameter.name());
} else {
ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return s == null ? null : Enum.valueOf(type, s);
...以下代碼展示了如何為確定枚舉類型的類型轉(zhuǎn)換器。

- 首先直接獲取對(duì)應(yīng)類型的類型型轉(zhuǎn)換器,包括原始類型,包括raw type(原始類型,對(duì)應(yīng)Class),parameterized types(參數(shù)化類型), array types(數(shù)組類型),這是最精確的匹配。
- 如果是Class類型且枚舉類型是其接口或父類,如果是匿名類,尋找其父類的類型轉(zhuǎn)換器,否則再不斷遞歸尋找該枚舉類的接口類型轉(zhuǎn)換器,如果沒有找到,直接利用反射獲defaultEnumHandler的的對(duì)象,專門用于處理該枚舉類型,在圖中是GroupStatusEnum。
- 如果不是枚舉類型,則再嘗試其父類。
getInstance方法如下
public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
if (javaTypeClass != null) {
try {
Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
return (TypeHandler<T>) c.newInstance(javaTypeClass);
} catch (NoSuchMethodException ignored) {
// ignored
} catch (Exception e) {
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
}
}
try {
Constructor<?> c = typeHandlerClass.getConstructor();
return (TypeHandler<T>) c.newInstance();
} catch (Exception e) {
throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
}
}自定義通用枚舉類型
為項(xiàng)目中所有枚舉類型定一個(gè)接口
public interface BaseEnum {
Integer getValue();
}枚舉類實(shí)現(xiàn)該接口
@AllArgsConstructor
@Getter
public enum GroupStatusEnum implements BaseEnum {
DISBANDED("已解散", 0),
NORMAL("正常", 1);
private final String desc;
private final Integer value;
}定義通用枚舉類型轉(zhuǎn)換器
public class GenericEnumHandler<E extends BaseEnum> implements TypeHandler<E> {
private final Map<Integer, E> map = new HashMap<>();
public GenericEnumHandler(Class<E> clazz) {
E[] constants = clazz.getEnumConstants();
for (E constant : constants) {
map.put(constant.getValue(), constant);
}
}
@Override
public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getValue());
}
@Override
public E getResult(ResultSet rs, String columnName) throws SQLException {
return map.get(rs.getInt(columnName));
}
@Override
public E getResult(ResultSet rs, int columnIndex) throws SQLException {
return map.get(rs.getInt(columnIndex));
}
@Override
public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
return map.get(cs.getInt(columnIndex));
}
}按照上述源碼分析流程,當(dāng)GroupStatusEnum第一次需要轉(zhuǎn)化數(shù)據(jù)庫的int時(shí),mybatis去尋找類型轉(zhuǎn)換器。
- 我們沒有為這種類型定義專門的類型轉(zhuǎn)換器(TypeHandler<GroupStatusEnum>)。
- 該類不是內(nèi)部類。
- 該類實(shí)現(xiàn)了BaseEnum接口,但是我們沒有為BaseEnum定義類型轉(zhuǎn)換器。
- 使用該類和默認(rèn)的枚舉類利用反射構(gòu)造一個(gè)對(duì)象處理該枚舉,即new GenericEnumTypeHandler(GroupStatusEnum.class)。
使用方法
mybatis:
configuration:
local-cache-scope: statement
jdbc-type-for-null: null
use-generated-keys: true
cache-enabled: false
map-underscore-to-camel-case: true
default-enum-type-handler: com.windcf.easychatjava.typehandler.GenericEnumHandler
mapper-locations: classpath:/mappers/**/*.xml
# type-handlers-package: com.windcf.easychatjava.typehandler到此這篇關(guān)于Mybatis枚舉類型轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)Mybatis枚舉類型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java之Set String List互轉(zhuǎn)方式
文章總結(jié)了Java中Set與String以及List之間的相互轉(zhuǎn)換方法,通過代碼示例展示了如何將Set轉(zhuǎn)為L(zhǎng)ist,再將List轉(zhuǎn)為Set,以及如何將List轉(zhuǎn)為String,最后又將String轉(zhuǎn)為L(zhǎng)ist的過程2026-04-04
Java代碼實(shí)現(xiàn)微信頁面滾動(dòng)防露底(核心代碼)
這篇文章主要介紹了Java代碼實(shí)現(xiàn)微信頁面滾動(dòng)防露底的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Java 定時(shí)器(Timer,TimerTask)詳解及實(shí)例代碼
這篇文章主要介紹了 Java 定時(shí)器(Timer,TimerTask)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-01-01
MyBatis-Plus?實(shí)體類注解的實(shí)現(xiàn)示例
MyBatis-Plus作為MyBatis的增強(qiáng)版,提供了一系列實(shí)用的注解,如@TableName、@TableId、@TableField等,旨在簡(jiǎn)化數(shù)據(jù)庫和Java實(shí)體類之間的映射及CRUD操作,通過這些注解,開發(fā)者可以輕松實(shí)現(xiàn)表映射、字段映射、邏輯刪除、自動(dòng)填充和樂觀鎖等功能2024-09-09
Java使用FreeMarker實(shí)現(xiàn)動(dòng)態(tài)生成Word文檔
在電纜行業(yè),生成供貨清單是一項(xiàng)常見但繁瑣的任務(wù),這篇文章將介紹如何使用現(xiàn)代Java技術(shù)棧自動(dòng)化這一過程,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以參考一下2025-05-05
java生成字母數(shù)字組合的隨機(jī)數(shù)示例 java生成隨機(jī)數(shù)
這篇文章主要介紹了java生成字母數(shù)字組合的隨機(jī)數(shù)的示例,大家參考使用吧2014-01-01
springboot如何通過@Value,@ConfigurationProperties獲取配置
這篇文章主要介紹了springboot如何通過@Value,@ConfigurationProperties獲取配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java Comparable 和 Comparator 的詳解及區(qū)別
這篇文章主要介紹了Java Comparable 和 Comparator 的詳解及區(qū)別的相關(guān)資料,Comparable 自然排序和Comparator 定制排序的實(shí)例,需要的朋友可以參考下2016-12-12
Java數(shù)據(jù)結(jié)構(gòu)之堆(優(yōu)先隊(duì)列)的實(shí)現(xiàn)
堆(優(yōu)先隊(duì)列)是一種典型的數(shù)據(jù)結(jié)構(gòu),其形狀是一棵完全二叉樹,一般用于求解topk問題。本文將利用Java語言實(shí)現(xiàn)堆,感興趣的可以學(xué)習(xí)一下2022-05-05

