Mybatis之類型處理器TypeHandler的作用與自定義方式
一、什么是類型處理器
1、類型處理器(TypeHandler)
MyBatis 在設置預處理語句(PreparedStatement)中的參數(shù)或從結果集中取出一個值時,都會用類型處理器將獲取到的值以合適的方式轉換成 Java 類型。
說人話,也就是java類型與jdbc類型之間的處換器,諸如最常見StringTypeHandler。
2、Mybatis內(nèi)置了哪些類型處理器
如下圖,類型處理器的頂級接口是org.apache.ibatis.type.TypeHandler
下表描述了一些默認的類型處理器,官方原表。
類型處理器 | Java 類型 | JDBC 類型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean, boolean | 數(shù)據(jù)庫兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 數(shù)據(jù)庫兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short, short | 數(shù)據(jù)庫兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler | java.lang.Integer, int | 數(shù)據(jù)庫兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long, long | 數(shù)據(jù)庫兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler | java.lang.Float, float | 數(shù)據(jù)庫兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double, double | 數(shù)據(jù)庫兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 數(shù)據(jù)庫兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB, LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR, NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 數(shù)據(jù)庫兼容的字節(jié)流類型 |
BlobTypeHandler | byte[] | BLOB, LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定類型 |
EnumTypeHandler | Enumeration Type | VARCHAR 或任何兼容的字符串類型,用來存儲枚舉的名稱(而不是索引序數(shù)值) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 類型,用來存儲枚舉的序數(shù)值(而不是名稱)。 |
SqlxmlTypeHandler | java.lang.String | SQLXML |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
二、如何自定義類型處理器
盡管mybatis提供了許多類型處理器,但有時由于業(yè)務的需要,需要自定義類型處理器。
例如,java實體類中Long[]數(shù)組類型如何以JSON字符串格式存儲到數(shù)據(jù)庫中varchar中,又如何能正常查詢出,此時就需要自定義類型了。
1、寫個處理器
實現(xiàn) org.apache.ibatis.type.TypeHandler 接口, 或繼承一個很便利的類org.apache.ibatis.type.BaseTypeHandler, 并且可以(可選地)將它映射到一個 JDBC 類型
是否要指定javaType與jdbcType?
官方解釋:要注意 MyBatis 不會通過檢測數(shù)據(jù)庫元信息來決定使用哪種類型,所以你必須在參數(shù)和結果映射中指明字段的jdbcType,以使其能夠綁定到正確的類型處理器上。這是因為 MyBatis 直到語句被執(zhí)行時才清楚數(shù)據(jù)類型。
關于javaType的指定,通過類型處理器的泛型,MyBatis 可以得知該類型處理器處理的 Java 類型,不過這種行為可以通過兩種方法改變:
- 在類型處理器的配置元素(typeHandler 元素)上增加一個 javaType 屬性(比如:javaType=“String”);
- 在類型處理器的類上增加一個 @MappedTypes 注解指定與其關聯(lián)的 Java 類型列表。 如果在 javaType 屬性中也同時指定,則注解上的配置將被忽略。
關于jdbcType的指定,可以通過兩種方式來指定關聯(lián)的 JDBC 類型:
- 在類型處理器的配置元素上增加一個 jdbcType 屬性(比如:jdbcType=“VARCHAR”);
- 在類型處理器的類上增加一個 @MappedJdbcTypes 注解指定與其關聯(lián)的 JDBC 類型列表。 如果在 jdbcType 屬性中也同時指定,則注解上的配置將被忽略。
當在 ResultMap 中決定使用哪種類型處理器時,此時 Java 類型是已知的(從結果類型中獲得),但是 JDBC 類型是未知的。 因此 Mybatis 使用 javaType=[Java 類型], jdbcType=null 的組合來選擇一個類型處理器。
這意味著使用 @MappedJdbcTypes 注解可以限制類型處理器的作用范圍,并且可以確保,除非顯式地設置,否則類型處理器在 ResultMap 中將不會生效。
如果希望能在 ResultMap 中隱式地使用類型處理器,那么設置 @MappedJdbcTypes 注解的 includeNullJdbcType=true 即可。
然而從 Mybatis 3.4.0 開始,如果某個 Java 類型只有一個注冊的類型處理器,即使沒有設置 includeNullJdbcType=true,那么這個類型處理器也會是 ResultMap 使用 Java 類型時的默認處理器。
2、配置處理器
全局配置,在mybatis配置文件中配置
局部配置,只針對某個字段處理,查與增刪改使用的typeHandler要保持一致
查:在resultMap中指定字段的typeHandler
增刪改:使用 #{} 指定typeHandler
3、驗證處理器
數(shù)據(jù)庫:
實體類:
查詢結果:
插入結果:
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot ThreadLocal 簡單介紹及使用詳解
ThreadLocal 叫做線程變量,意思是 ThreadLocal 中填充的變量屬于當前線程,該變量對其他線程而言是隔離的,也就是說該變量是當前線程獨有的變量,這篇文章主要介紹了SpringBoot ThreadLocal 的詳解,需要的朋友可以參考下2024-01-01基于springboot bean的實例化過程和屬性注入過程
這篇文章主要介紹了基于springboot bean的實例化過程和屬性注入過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11詳解Spring Boot的GenericApplicationContext使用教程
這篇教程展示了如何在Spring應用程序中使用GenericApplicationContext 。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11MyBatis insert操作插入數(shù)據(jù)之后返回插入記錄的id
今天小編就為大家分享一篇關于MyBatis插入數(shù)據(jù)之后返回插入記錄的id,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境全過程
眾所周知Ubuntu是一種基于Linux的操作系統(tǒng),它提供了一個穩(wěn)定、安全和易于使用的環(huán)境,下面這篇文章主要給大家介紹了關于Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-07-07