MyBatis 管理和查找TypeHandler的方法
MyBatis 通過 TypeHandlerRegistry
組件來(lái)集中 管理和查找 TypeHandler。 TypeHandler
是 MyBatis 中用于 處理 Java 類型和 JDBC 類型之間轉(zhuǎn)換 的重要組件。 MyBatis 需要管理大量的 TypeHandler,并能夠根據(jù)需要快速找到合適的 TypeHandler 來(lái)進(jìn)行類型轉(zhuǎn)換。
1. TypeHandlerRegistry 的作用:TypeHandler 的注冊(cè)中心
TypeHandlerRegistry
可以被理解為 MyBatis 中 TypeHandler 的注冊(cè)中心 或 TypeHandler 的倉(cāng)庫(kù)。 它的核心作用是:
- 注冊(cè) TypeHandler: 負(fù)責(zé)注冊(cè)各種 TypeHandler 到 MyBatis 系統(tǒng)中。 TypeHandler 可以是 MyBatis 內(nèi)置的,也可以是用戶自定義的。
- 存儲(chǔ) TypeHandler: 內(nèi)部維護(hù)一個(gè)數(shù)據(jù)結(jié)構(gòu) (實(shí)際上是多個(gè)
Map
) 來(lái)存儲(chǔ)已注冊(cè)的 TypeHandler,并按照不同的維度進(jìn)行組織,方便查找。 - 查找 TypeHandler: 提供 API 方法,允許 MyBatis 在運(yùn)行時(shí)根據(jù) Java 類型和/或 JDBC 類型,快速查找并獲取合適的 TypeHandler 實(shí)例。
2. TypeHandlerRegistry 如何管理 TypeHandler:內(nèi)部存儲(chǔ)結(jié)構(gòu)
TypeHandlerRegistry
內(nèi)部使用多個(gè) Map
來(lái)存儲(chǔ) TypeHandler,以便根據(jù)不同的查找條件進(jìn)行高效檢索。 主要的存儲(chǔ)結(jié)構(gòu)包括:
KNOWN_TYPE_HANDLERS
(Map<JdbcType, TypeHandler<?>>):
- Key: JdbcType 枚舉值,代表 JDBC 類型。
- Value: TypeHandler<?> 實(shí)例。
- 作用: 根據(jù) JDBC 類型查找 TypeHandler。 例如,當(dāng) MyBatis 需要處理 VARCHAR 類型的參數(shù)或結(jié)果時(shí),會(huì)使用 KNOWN_TYPE_HANDLERS 查找與 JdbcType.VARCHAR 關(guān)聯(lián)的 TypeHandler。
TYPE_HANDLER_MAP
(Map<Type, Map<JdbcType, TypeHandler<?>>>):
- Outer Key:
Type
對(duì)象,代表 Java 類型。 - Inner Key:
JdbcType
枚舉值,代表 JDBC 類型 (可以為null
,表示不區(qū)分 JDBC 類型)。 - Value:
TypeHandler<?>
實(shí)例。 - 作用: 根據(jù) Java 類型和 JDBC 類型查找 TypeHandler。 這是最主要的 TypeHandler 存儲(chǔ)和查找結(jié)構(gòu)。 MyBatis 會(huì)優(yōu)先使用
TYPE_HANDLER_MAP
進(jìn)行查找。 - 層級(jí)結(jié)構(gòu):
TYPE_HANDLER_MAP
是一個(gè)兩層嵌套的Map
。 外層Map
的 Key 是 Java 類型,內(nèi)層Map
的 Key 是 JDBC 類型。 這種結(jié)構(gòu)允許根據(jù) Java 類型和 JDBC 類型的組合來(lái)精確查找 TypeHandler。
ALL_TYPE_HANDLERS_MAP
(Map<Class<?>, TypeHandler<?>>):
- Key:
Class<?>
對(duì)象,代表 TypeHandler 的 Class 類型。 - Value:
TypeHandler<?>
實(shí)例。 - 作用: 根據(jù) TypeHandler 的 Class 類型查找 TypeHandler 實(shí)例。 主要用于通過
TypeHandlerRegistry.getTypeHandler(Class<? extends TypeHandler> handlerType)
方法直接根據(jù) TypeHandler 類型查找實(shí)例。
3. TypeHandler 的注冊(cè)方式:
TypeHandler 可以通過多種方式注冊(cè)到 TypeHandlerRegistry
中:
3.1. XML 配置文件 (mybatis-config.xml):
<typeHandlers>
元素和 <typeHandler>
子元素: 在 mybatis-config.xml
文件中使用 <typeHandlers>
元素和 <typeHandler>
子元素來(lái)注冊(cè) TypeHandler。
<typeHandlers> <typeHandler javaType="java.lang.String" jdbcType="VARCHAR" handler="com.example.typehandler.MyStringTypeHandler"/> <typeHandler package="com.example.typehandler.package"/> <!-- 掃描包注冊(cè) TypeHandler --> </typeHandlers>
javaType
屬性 (可選): 指定 TypeHandler 處理的 Java 類型。 可以指定多個(gè) Java 類型,用逗號(hào)分隔。jdbcType
屬性 (可選): 指定 TypeHandler 處理的 JDBC 類型。 可以指定多個(gè) JDBC 類型,用逗號(hào)分隔。handler
屬性: 指定 TypeHandler 實(shí)現(xiàn)類的全限定名。<typeHandler package="...">
: 指定包名,MyBatis 會(huì)掃描指定包下的所有 TypeHandler,并自動(dòng)注冊(cè)。
XMLConfigBuilder
解析 <typeHandlers>
元素時(shí),會(huì)將配置的 TypeHandler 注冊(cè)到 Configuration
對(duì)象的 typeHandlerRegistry
中。
3.2. Java 代碼配置 (Configuration 對(duì)象):
Configuration.getTypeHandlerRegistry().register(...)
方法: 可以通過 Configuration
對(duì)象的 getTypeHandlerRegistry()
方法獲取 TypeHandlerRegistry
實(shí)例,然后使用 register()
方法手動(dòng)注冊(cè) TypeHandler。
Configuration configuration = new Configuration(); TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); typeHandlerRegistry.register(String.class, JdbcType.VARCHAR, new MyStringTypeHandler()); // 注冊(cè)指定 Java 類型和 JDBC 類型的 TypeHandler typeHandlerRegistry.register(MyEnumTypeHandler.class); // 注冊(cè) TypeHandler,不指定 Java 類型和 JDBC 類型 (MyEnumTypeHandler 需要標(biāo)注 @MappedTypes 和 @MappedJdbcTypes) typeHandlerRegistry.register(new MyDefaultTypeHandler()); // 注冊(cè) TypeHandler 實(shí)例,不指定 Java 類型和 JDBC 類型 (MyDefaultTypeHandler 需要標(biāo)注 @MappedTypes 和 @MappedJdbcTypes)
register(TypeHandler<?> typeHandler)
: 注冊(cè) TypeHandler 實(shí)例。TypeHandler 類需要使用@MappedTypes
和@MappedJdbcTypes
注解指定它處理的 Java 類型和 JDBC 類型。register(Class<?> javaType, TypeHandler<?> typeHandler)
: 注冊(cè)指定 Java 類型的 TypeHandler 實(shí)例。register(JdbcType jdbcType, TypeHandler<?> typeHandler)
: 注冊(cè)指定 JDBC 類型的 TypeHandler 實(shí)例。register(Class<?> javaType, JdbcType jdbcType, TypeHandler<?> typeHandler)
: 注冊(cè)指定 Java 類型和 JDBC 類型的 TypeHandler 實(shí)例。register(String typeHandlerName)
: 根據(jù) TypeHandler 的別名注冊(cè) TypeHandler (別名需要在<typeAliases>
中定義)。
3.3. 自動(dòng)掃描包 (<typeHandlers package="...">):
- 通過在
<typeHandlers>
元素中使用<typeHandler package="...">
子元素,可以指定包名。 MyBatis 會(huì) 自動(dòng)掃描指定包及其子包下的所有 TypeHandler 實(shí)現(xiàn)類,并將它們注冊(cè)到TypeHandlerRegistry
中。 - TypeHandler 類需要使用
@MappedTypes
和@MappedJdbcTypes
注解來(lái)聲明它處理的 Java 類型和 JDBC 類型。
3.4. MyBatis 內(nèi)置的 TypeHandler:
- MyBatis 框架內(nèi)置了大量的常用 TypeHandler,用于處理 Java 基本類型、常用 Java 類型 (例如 String, Date, Enum) 和 JDBC 類型之間的轉(zhuǎn)換。
- 這些內(nèi)置的 TypeHandler 在
TypeHandlerRegistry
初始化時(shí)會(huì)被自動(dòng)注冊(cè),無(wú)需顯式配置。 例如:StringTypeHandler
,IntegerTypeHandler
,DateTypeHandler
,EnumTypeHandler
等。
4. TypeHandlerRegistry 如何查找 TypeHandler:查找策略
當(dāng) MyBatis 需要進(jìn)行類型轉(zhuǎn)換時(shí) (例如設(shè)置 PreparedStatement 參數(shù),獲取 ResultSet 結(jié)果),會(huì)通過 TypeHandlerRegistry
查找合適的 TypeHandler。 TypeHandlerRegistry
的查找策略如下 (優(yōu)先級(jí)從高到低):
4.1. 精確匹配 Java 類型和 JDBC 類型:
MyBatis 會(huì)首先嘗試 根據(jù) Java 類型和 JDBC 類型的精確組合 在 TYPE_HANDLER_MAP
中查找 TypeHandler。 這是最精確的查找方式,如果找到,則直接使用該 TypeHandler。
4.2. 匹配 Java 類型,忽略 JDBC 類型:
如果精確匹配 Java 類型和 JDBC 類型沒有找到 TypeHandler,MyBatis 會(huì)嘗試 只根據(jù) Java 類型 在 TYPE_HANDLER_MAP
中查找 TypeHandler (JDBC 類型設(shè)置為 null
)。 這種方式適用于某些 TypeHandler 只需要根據(jù) Java 類型進(jìn)行處理,而不需要區(qū)分 JDBC 類型的情況。
4.3. 根據(jù) JDBC 類型查找:
如果根據(jù) Java 類型和 JDBC 類型都無(wú)法找到合適的 TypeHandler,MyBatis 會(huì)嘗試 根據(jù) JDBC 類型 在 KNOWN_TYPE_HANDLERS
中查找 TypeHandler。 這種方式適用于某些通用的 JDBC 類型處理場(chǎng)景,例如處理所有 VARCHAR
類型的數(shù)據(jù),可以使用與 JdbcType.VARCHAR
關(guān)聯(lián)的 TypeHandler。
4.4. 類型繼承關(guān)系查找 (Type Hierarchy):
如果以上方式都無(wú)法找到合適的 TypeHandler,MyBatis 還會(huì) 考慮 Java 類型的繼承關(guān)系。 例如,如果查找 List
類型的 TypeHandler 失敗,MyBatis 會(huì)嘗試查找 Collection
, Iterable
, Object
等父類型或接口的 TypeHandler。 這種方式可以提高 TypeHandler 的通用性。
4.5. 默認(rèn) TypeHandler (Default TypeHandler):
如果經(jīng)過上述所有查找策略都無(wú)法找到合適的 TypeHandler,MyBatis 會(huì) 使用默認(rèn)的 ObjectTypeHandler
(或其他默認(rèn) TypeHandler) 進(jìn)行處理。 ObjectTypeHandler
可以處理 Object
類型的數(shù)據(jù),但可能會(huì)丟失類型信息,性能也可能較低。
5. 關(guān)鍵組件和類:
TypeHandlerRegistry
: TypeHandler 注冊(cè)中心,負(fù)責(zé)管理和查找 TypeHandler。TypeHandler
接口: 所有 TypeHandler 實(shí)現(xiàn)類都需要實(shí)現(xiàn)的接口,定義了類型轉(zhuǎn)換的方法 (setParameter()
,getResult()
).Configuration
對(duì)象:TypeHandlerRegistry
實(shí)例存儲(chǔ)在Configuration
對(duì)象中。XMLConfigBuilder
: 在解析mybatis-config.xml
文件時(shí),XMLConfigBuilder
負(fù)責(zé)解析<typeHandlers>
元素,并將配置的 TypeHandler 注冊(cè)到Configuration
對(duì)象的typeHandlerRegistry
中。JdbcType
枚舉: 定義了 JDBC 類型常量。Type
接口 (Java Reflection API): 表示 Java 類型。
總結(jié)
TypeHandlerRegistry
的作用和 TypeHandler 的管理和查找機(jī)制:TypeHandlerRegistry
是 MyBatis 中 TypeHandler 的注冊(cè)中心,負(fù)責(zé)管理和維護(hù)所有已注冊(cè)的 TypeHandler。TypeHandler 可以通過 XML 配置、Java 代碼配置、自動(dòng)掃描包和 MyBatis 內(nèi)置等多種方式注冊(cè)到TypeHandlerRegistry
中。TypeHandlerRegistry
使用多層Map
結(jié)構(gòu)存儲(chǔ) TypeHandler,并提供高效的查找策略,可以根據(jù) Java 類型、JDBC 類型和類型繼承關(guān)系等條件查找合適的 TypeHandler。MyBatis 在運(yùn)行時(shí)需要進(jìn)行類型轉(zhuǎn)換時(shí),會(huì)委托TypeHandlerRegistry
查找合適的 TypeHandler,并使用找到的 TypeHandler 進(jìn)行類型轉(zhuǎn)換操作。TypeHandlerRegistry
的管理和查找機(jī)制保證了 MyBatis 能夠靈活、高效地處理各種 Java 類型和 JDBC 類型之間的轉(zhuǎn)換,實(shí)現(xiàn)了類型轉(zhuǎn)換的解耦和可擴(kuò)展性。
到此這篇關(guān)于MyBatis 管理和查找TypeHandler的方法的文章就介紹到這了,更多相關(guān)MyBatis 查找TypeHandler內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決
- 解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題
- Mybatis之類型處理器TypeHandler的作用與自定義方式
- mybatis-plus之自動(dòng)映射字段(typeHandler)的注意點(diǎn)及說明
- MybatisPlus如何自定義TypeHandler映射JSON類型為L(zhǎng)ist
- MyBatis-Plus如何通過注解使用TypeHandler
- Mybatis實(shí)戰(zhàn)之TypeHandler高級(jí)進(jìn)階
相關(guān)文章
Java實(shí)用工具庫(kù)commons-lang3的使用
Apache?Commons?Lang?3是一個(gè)流行的Java實(shí)用工具庫(kù),提供了對(duì)java.lang包的擴(kuò)展,包括字符串操作、正則表達(dá)式處理、數(shù)字操作、日期和時(shí)間操作、隨機(jī)字符串生成和對(duì)象操作等功能2025-03-03MyBatis Mapper XML中比較操作符轉(zhuǎn)義問題解決
在使用MyBatis編寫Mapper XML時(shí),有時(shí)會(huì)遇到比較操作符需要進(jìn)行轉(zhuǎn)義的情況,本文主要介紹了MyBatis Mapper XML中比較操作符轉(zhuǎn)義問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01spring boot task實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建定時(shí)任務(wù)的方法
這篇文章主要介紹了spring boot task實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建定時(shí)任務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-01-01解決MybatisPlus批量插入數(shù)據(jù)報(bào)錯(cuò):Error getting generated 
在使用MybatisPlus進(jìn)行批量插入數(shù)據(jù)時(shí)遇到空指針異常錯(cuò)誤,分析原因是由于主鍵生成策略導(dǎo)致的,嘗試通過設(shè)置useGeneratedKeys屬性解決問題,但因批量插入方法限制,該方法未能成功,最終通過自定義mapper方法實(shí)現(xiàn)批量插入,解決了問題2024-09-09