Mybatis枚舉類型轉(zhuǎn)換源碼分析
Mybatis枚舉類型轉(zhuǎn)換
類型轉(zhuǎn)換器源碼分析
在Mybatis的TypeHandlerRegistry中,添加了常用的類轉(zhuǎ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,默認使用的是枚舉的名稱設置參數(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)換器。
- 首先直接獲取對應類型的類型型轉(zhuǎn)換器,包括原始類型,包括raw type(原始類型,對應Class),parameterized types(參數(shù)化類型), array types(數(shù)組類型),這是最精確的匹配。
- 如果是Class類型且枚舉類型是其接口或父類,如果是匿名類,尋找其父類的類型轉(zhuǎn)換器,否則再不斷遞歸尋找該枚舉類的接口類型轉(zhuǎn)換器,如果沒有找到,直接利用反射獲defaultEnumHandler的的對象,專門用于處理該枚舉類型,在圖中是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); } }
自定義通用枚舉類型
為項目中所有枚舉類型定一個接口
public interface BaseEnum { Integer getValue(); }
枚舉類實現(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)); } }
按照上述源碼分析流程,當GroupStatusEnum第一次需要轉(zhuǎn)化數(shù)據(jù)庫的int時,mybatis去尋找類型轉(zhuǎn)換器。
- 我們沒有為這種類型定義專門的類型轉(zhuǎn)換器(TypeHandler<GroupStatusEnum>)。
- 該類不是內(nèi)部類。
- 該類實現(xiàn)了BaseEnum接口,但是我們沒有為BaseEnum定義類型轉(zhuǎn)換器。
- 使用該類和默認的枚舉類利用反射構(gòu)造一個對象處理該枚舉,即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
到此這篇關于Mybatis枚舉類型轉(zhuǎn)換的文章就介紹到這了,更多相關Mybatis枚舉類型轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解SpringBoot中@NotNull,@NotBlank注解使用
這篇文章主要為大家詳細介紹了Spring?Boot中集成Validation與@NotNull,@NotBlank等注解的簡單使用,感興趣的小伙伴可以跟隨小編一起學習一下2022-08-08springboot 多環(huán)境配置 yml文件版的實現(xiàn)方法
這篇文章主要介紹了springboot 多環(huán)境配置 yml文件版的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06Spring?Boot自動配置的原理及@Conditional條件注解
這篇文章主要介紹了Spring?Boot自動配置的原理及@Conditional條件注解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的朋友可以參考一下2022-07-07SpringCloud的@RefreshScope 注解你了解嗎
這篇文章主要介紹了Spring Cloud @RefreshScope 原理及使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-09-09