MyBatis類型處理器TypeHandler的作用及說(shuō)明
TypeHandler
是 MyBatis 中用于處理 Java 類型與 JDBC 類型之間轉(zhuǎn)換的接口。它在 MyBatis 的參數(shù)綁定和結(jié)果映射過(guò)程中起著至關(guān)重要的作用。
為什么需要 TypeHandler?
Java 和 數(shù)據(jù)庫(kù)(JDBC)使用不同的類型系統(tǒng)。例如:
- Java 中有
String
、Integer
、Date
、Boolean
、enum
等類型。 - JDBC 中有
VARCHAR
、INTEGER
、DATE
、BOOLEAN
、TIMESTAMP
、BLOB
等類型。
當(dāng) MyBatis 執(zhí)行 SQL 語(yǔ)句時(shí),需要將 Java 對(duì)象中的數(shù)據(jù)設(shè)置到 JDBC 的 PreparedStatement
中(參數(shù)綁定),以及將 JDBC 的 ResultSet
中的數(shù)據(jù)轉(zhuǎn)換為 Java 對(duì)象(結(jié)果映射)。TypeHandler
就負(fù)責(zé)處理這兩種情況下的類型轉(zhuǎn)換。
TypeHandler 的作用
參數(shù)綁定 (Java 類型 -> JDBC 類型):
- 當(dāng) MyBatis 將 Java 對(duì)象中的數(shù)據(jù)設(shè)置到
PreparedStatement
的占位符(#{}
)時(shí),TypeHandler
會(huì)將 Java 類型轉(zhuǎn)換為對(duì)應(yīng)的 JDBC 類型。 - 例如,將 Java 的
String
類型轉(zhuǎn)換為 JDBC 的VARCHAR
類型,將 Java 的Date
類型轉(zhuǎn)換為 JDBC 的TIMESTAMP
類型。
結(jié)果映射 (JDBC 類型 -> Java 類型):
- 當(dāng) MyBatis 從
ResultSet
中讀取數(shù)據(jù)并將其映射為 Java 對(duì)象時(shí),TypeHandler
會(huì)將 JDBC 類型轉(zhuǎn)換為對(duì)應(yīng)的 Java 類型。 - 例如,將 JDBC 的
VARCHAR
類型轉(zhuǎn)換為 Java 的String
類型,將 JDBC 的INTEGER
類型轉(zhuǎn)換為 Java 的Integer
類型。
TypeHandler 的接口定義
public interface TypeHandler<T> { // 參數(shù)綁定:將 Java 類型轉(zhuǎn)換為 JDBC 類型,并設(shè)置到 PreparedStatement 中 void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; // 結(jié)果映射:從 ResultSet 中獲取指定列的數(shù)據(jù),并將其轉(zhuǎn)換為 Java 類型 T getResult(ResultSet rs, String columnName) throws SQLException; // 結(jié)果映射:從 ResultSet 中獲取指定列索引的數(shù)據(jù),并將其轉(zhuǎn)換為 Java 類型 T getResult(ResultSet rs, int columnIndex) throws SQLException; // 結(jié)果映射:從 CallableStatement 中獲取指定列索引的數(shù)據(jù),將其轉(zhuǎn)換為java類型 T getResult(CallableStatement cs, int columnIndex) throws SQLException; }
setParameter()
: 將 Java 類型的參數(shù)parameter
設(shè)置到PreparedStatement
的第i
個(gè)占位符,并指定 JDBC 類型jdbcType
(jdbcType
可以為空,MyBatis 會(huì)嘗試自動(dòng)推斷)。getResult()
: 有三個(gè)重載方法,分別根據(jù)列名、列索引從ResultSet
中獲取數(shù)據(jù),或從CallableStatement
獲取數(shù)據(jù),并將其轉(zhuǎn)換為 Java 類型。
MyBatis 內(nèi)置的 TypeHandler
MyBatis 內(nèi)置了許多常用的 TypeHandler
,用于處理常見(jiàn)的類型轉(zhuǎn)換。例如:
StringTypeHandler
: 處理String
類型。IntegerTypeHandler
: 處理Integer
類型。LongTypeHandler
: 處理Long
類型。DateTypeHandler
: 處理java.util.Date
類型。BooleanTypeHandler
: 處理Boolean
類型。EnumTypeHandler
: 處理枚舉類型(默認(rèn)使用枚舉的名稱)。EnumOrdinalTypeHandler
: 處理枚舉類型(使用枚舉的序數(shù))。BlobTypeHandler
: 處理二進(jìn)制大對(duì)象 (BLOB)。ClobTypeHandler
: 處理字符大對(duì)象 (CLOB)。SqlDateTypeHandler
:處理java.sql.Date
類型SqlTimeTypeHandler
:處理java.sql.Time
類型SqlTimestampTypeHandler
:處理java.sql.Timestamp
類型- …
自定義 TypeHandler
當(dāng) MyBatis 內(nèi)置的 TypeHandler
不能滿足需求時(shí),我們可以自定義 TypeHandler
。例如:
- 處理特殊類型: 例如,將數(shù)據(jù)庫(kù)中的 JSON 字符串轉(zhuǎn)換為 Java 對(duì)象,或者將 Java 對(duì)象轉(zhuǎn)換為 JSON 字符串存儲(chǔ)到數(shù)據(jù)庫(kù)中。
- 自定義類型轉(zhuǎn)換邏輯: 例如,對(duì)日期類型進(jìn)行特殊的格式化,或者對(duì)枚舉類型使用自定義的轉(zhuǎn)換規(guī)則。
自定義 TypeHandler 的步驟
1.實(shí)現(xiàn) TypeHandler
接口: 創(chuàng)建一個(gè)類,實(shí)現(xiàn) TypeHandler
接口,并實(shí)現(xiàn)接口中的方法。
2.注冊(cè) TypeHandler: 有兩種方式注冊(cè)自定義的 TypeHandler
:
- XML 配置: 在
mybatis-config.xml
文件中,使用<typeHandlers>
標(biāo)簽注冊(cè)TypeHandler
。
<typeHandlers> <typeHandler handler="com.example.MyTypeHandler" javaType="com.example.MyType" jdbcType="VARCHAR"/> </typeHandlers>
- 或者使用包掃描:
<typeHandlers> <package name="com.example.typehandler"/> </typeHandlers>
- 注解配置: 在自定義的
TypeHandler
類上使用@MappedTypes
和@MappedJdbcTypes
注解。
@MappedTypes(MyType.class) // 指定 Java 類型 @MappedJdbcTypes(JdbcType.VARCHAR) // 指定 JDBC 類型 public class MyTypeHandler implements TypeHandler<MyType> { // ... 實(shí)現(xiàn) TypeHandler 接口的方法 ... }
3.指定jdbcType(可選): 如果MyBatis無(wú)法推斷,則必須通過(guò)jdbcType
屬性為null
值指定數(shù)據(jù)庫(kù)列的類型
- 示例:
- 自定義一個(gè)將數(shù)據(jù)庫(kù)中的 VARCHAR 類型轉(zhuǎn)換為 Java 中的枚舉類型的 TypeHandler:
// 假設(shè)有一個(gè)枚舉類型 public enum Status { ACTIVE, INACTIVE, PENDING } // 自定義 TypeHandler @MappedTypes(Status.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class StatusTypeHandler implements TypeHandler<Status> { @Override public void setParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException { if (parameter == null) { ps.setString(i, null); } else { ps.setString(i, parameter.name()); // 將枚舉的名稱存儲(chǔ)到數(shù)據(jù)庫(kù) } } @Override public Status getResult(ResultSet rs, String columnName) throws SQLException { String value = rs.getString(columnName); return getStatus(value); } @Override public Status getResult(ResultSet rs, int columnIndex) throws SQLException { String value = rs.getString(columnIndex); return getStatus(value); } @Override public Status getResult(CallableStatement cs, int columnIndex) throws SQLException { String value = cs.getString(columnIndex); return getStatus(value); } private Status getStatus(String value){ if (value == null) { return null; } try { return Status.valueOf(value); // 根據(jù)名稱從數(shù)據(jù)庫(kù)中獲取枚舉值 } catch (IllegalArgumentException e) { return null; // 或者拋出異常 } } } // 在 mybatis-config.xml 中注冊(cè) TypeHandler <typeHandlers> <typeHandler handler="com.example.StatusTypeHandler"/> </typeHandlers> // 或者在 Mapper XML 文件中使用 <resultMap id="userResultMap" type="User"> <result property="status" column="status" javaType="com.example.Status" jdbcType="VARCHAR" typeHandler="com.example.StatusTypeHandler"/> </resultMap>
總結(jié)
TypeHandler
是 MyBatis 中用于處理 Java 類型與 JDBC 類型之間轉(zhuǎn)換的關(guān)鍵組件。
MyBatis 內(nèi)置了許多常用的 TypeHandler
,在大多數(shù)情況下,我們可以直接使用內(nèi)置的 TypeHandler
。
當(dāng)需要處理特殊類型或自定義類型轉(zhuǎn)換邏輯時(shí),我們可以自定義 TypeHandler
,并通過(guò) XML 配置或注解的方式注冊(cè)自定義的 TypeHandler
。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- MyBatis?typeHandler接口的定義和使用
- MyBatis中的自定義TypeHandler詳解
- Mybatis中自定義TypeHandler處理枚舉的示例代碼
- Mybatis的TypeHandler實(shí)現(xiàn)數(shù)據(jù)加解密詳解
- Mybatis中TypeHandler使用小結(jié)
- SpringBoot中MyBatis使用自定義TypeHandler的實(shí)現(xiàn)
- Mybatis使用typeHandler加密的實(shí)現(xiàn)
- MyBatis-Plus?中?typeHandler?的使用實(shí)例詳解
- MyBatis中TypeHandler的使用教程詳解
- MyBatis自定義TypeHandler實(shí)現(xiàn)字段加密解密
相關(guān)文章
idea運(yùn)行vue項(xiàng)目設(shè)置自定義瀏覽器方式
這篇文章主要介紹了idea運(yùn)行vue項(xiàng)目設(shè)置自定義瀏覽器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08Java 程序設(shè)計(jì)總復(fù)習(xí)題(java基礎(chǔ)代碼)
這篇文章主要介紹了Java 程序設(shè)計(jì)總復(fù)習(xí)題,主要是java基礎(chǔ)代碼,方便學(xué)習(xí)java的同學(xué)2021-05-05SpringBoot3+ShardingJDBC5.5.0 讀寫(xiě)分離配置的實(shí)現(xiàn)
本文主要介紹了SpringBoot3+ShardingJDBC5.5.0 讀寫(xiě)分離配置的實(shí)現(xiàn),最新版5.5.0支持SpringBoot3x現(xiàn)分享給大家,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08JavaMail實(shí)現(xiàn)郵件發(fā)送機(jī)制
這篇文章主要為大家詳細(xì)介紹了JavaMail實(shí)現(xiàn)郵件發(fā)送機(jī)制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Java使用抽象工廠模式實(shí)現(xiàn)的肯德基消費(fèi)案例詳解
這篇文章主要介紹了Java使用抽象工廠模式實(shí)現(xiàn)的肯德基消費(fèi)案例,較為詳細(xì)的分析了抽象工廠模式的定義、原理并結(jié)合實(shí)例形式分析了Java使用抽象工廠模式實(shí)現(xiàn)肯德基消費(fèi)案例的步驟與相關(guān)操作技巧,需要的朋友可以參考下2018-05-05