原創(chuàng)作品,可以轉(zhuǎn)載,但是請標(biāo)注出處地址:http://www.cnblogs.com/V1haoge/p/6709157.html
1、回顧
上一篇研究的是類型別名注冊器TypeAliasRegister,它主要用于將基本類型和用戶自定義的類型進(jìn)行別名注冊,將別名及其對應(yīng)類類型保存在一個HashMap中,方便存取,是映射器映射功能實現(xiàn)的基礎(chǔ),本篇所研究的類型處理器注冊器TypeHandlerReister是用來統(tǒng)籌管理類型處理器的,類型處理器是真正用于進(jìn)行java類型與數(shù)據(jù)庫類型映射的工具。
這一篇我們還是重點(diǎn)研究類型處理器的注冊器,有關(guān)具體類型處理器的研究放到之后進(jìn)行。
2、類型處理器
為了研究類型處理器注冊器,我們需要對類型處理器有一定的基礎(chǔ)和認(rèn)識,這里簡單介紹一下,具體內(nèi)容可等下一篇。
類型處理器簡單點(diǎn)說就是用于處理javaType與jdbcType之間類型轉(zhuǎn)換用的處理器,MyBatis針對諸多Java類型與數(shù)據(jù)庫類型進(jìn)行了匹配處理。
它主要用于映射器配置文件的工作,在通過類型別名注冊器獲取類型別名代表的類型之后,就可以使用獲取的類型通過類型處理器注冊器來得到其對應(yīng)的JdbcType和對應(yīng)的類型處理器。
由此可見每個類型處理器都針對兩個類型,一個Java類型,一個數(shù)據(jù)庫類型。而類型處理器的作用就是進(jìn)行二者之間的匹配、對應(yīng)、轉(zhuǎn)換。
3、類型處理器注冊器
類型處理器注冊器既能完成類型處理器的注冊功能,同時也能對類型處理器進(jìn)行統(tǒng)籌管理,其內(nèi)部定義了集合來進(jìn)行類型處理器的存取,同時定義了存取方法。
1 private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);2 private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>();3 private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();
以上是TypeHandlerRegister中定義的三個Map集合,這三個集合是用來保存類型處理器的注冊信息的。
第一種:JDBC_TYPE_HANDLER_MAP,這是一個枚舉Map集合,其內(nèi)部是以JdbcType枚舉類中枚舉值為鍵創(chuàng)建的一種集合,這種集合先天存在鍵(枚舉值),它是以數(shù)據(jù)庫類型為鍵來保存類型處理器,亦即將類型處理器注冊到對應(yīng)的數(shù)據(jù)庫類型上。
第二種:TYPE_HANDLER_MAP,這是一個前套Map集合,內(nèi)層集合是以數(shù)據(jù)庫類型為鍵保存處理器,外層集合為以Java類型來保存對應(yīng)的數(shù)據(jù)庫類型及其處理器,這個集合將三者聯(lián)系起來,是真正進(jìn)行三者對應(yīng)關(guān)系匹配的集合。
第三種:ALL_TYPE_HANDLERS_MAP,這個集合中保存著所有的類型處理器,是以類型處理器的類類型為鍵值保存的,它可以統(tǒng)籌所有的類型處理器(帶有統(tǒng)計的效果)。
3.1 基礎(chǔ)類型處理器
在創(chuàng)建類型處理器注冊器的時候,在其無參構(gòu)造器中會進(jìn)行基礎(chǔ)類型處理器的注冊,這些注冊包括三種方式,一種是將以JavaType為鍵的保存方式,一種是以JdbcTye為鍵的保存方式,還有一種就是以JavaType與JdbcType為鍵的保存方式,這最后一種保存方式是一種嵌套的Map集合,前面的兩種只是簡單的Map集合。
下面將該無參構(gòu)造器源碼羅列:
1 //構(gòu)造函數(shù)里注冊系統(tǒng)內(nèi)置的類型處理器 2 public TypeHandlerRegistry() { 3 //以下是為多個類型注冊到同一個handler 4 register(Boolean.class, new BooleanTypeHandler()); 5 register(boolean.class, new BooleanTypeHandler()); 6 register(JdbcType.BOOLEAN, new BooleanTypeHandler()); 7 register(JdbcType.BIT, new BooleanTypeHandler()); 8 9 register(Byte.class, new ByteTypeHandler());10 register(byte.class, new ByteTypeHandler());11 register(JdbcType.TINYINT, new ByteTypeHandler());12 13 register(Short.class, new ShortTypeHandler());14 register(short.class, new ShortTypeHandler());15 register(JdbcType.SMALLINT, new ShortTypeHandler());16 17 register(Integer.class, new IntegerTypeHandler());18 register(int.class, new IntegerTypeHandler());19 register(JdbcType.INTEGER, new IntegerTypeHandler());20 21 register(Long.class, new LongTypeHandler());22 register(long.class, new LongTypeHandler());23 24 register(Float.class, new FloatTypeHandler());25 register(float.class, new FloatTypeHandler());26 register(JdbcType.FLOAT, new FloatTypeHandler());27 28 register(Double.class, new DoubleTypeHandler());29 register(double.class, new DoubleTypeHandler());30 register(JdbcType.DOUBLE, new DoubleTypeHandler());31 32 //以下是為同一個類型的多種變種注冊到多個不同的handler33 register(String.class, new StringTypeHandler());34 register(String.class, JdbcType.CHAR, new StringTypeHandler());35 register(String.class, JdbcType.CLOB, new ClobTypeHandler());36 register(String.class, JdbcType.VARCHAR, new StringTypeHandler());37 register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());38 register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());39 register(String.class, JdbcType.NCHAR, new NStringTypeHandler());40 register(String.class, JdbcType.NCLOB, new NClobTypeHandler());41 register(JdbcType.CHAR, new StringTypeHandler());42 register(JdbcType.VARCHAR, new StringTypeHandler());43 register(JdbcType.CLOB, new ClobTypeHandler());44 register(JdbcType.LONGVARCHAR, new ClobTypeHandler());45 register(JdbcType.NVARCHAR, new NStringTypeHandler());46 register(JdbcType.NCHAR, new NStringTypeHandler());47 register(JdbcType.NCLOB, new NClobTypeHandler());48 49 register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());50 register(JdbcType.ARRAY, new ArrayTypeHandler());51 52 register(BigInteger.class, new BigIntegerTypeHandler());53 register(JdbcType.BIGINT, new LongTypeHandler());54 55 register(BigDecimal.class, new BigDecimalTypeHandler());56 register(JdbcType.REAL, new BigDecimalTypeHandler());57 register(JdbcType.DECIMAL, new BigDecimalTypeHandler());58 register(JdbcType.NUMERIC, new BigDecimalTypeHandler());59 60 register(Byte[].class, new ByteObjectArrayTypeHandler());61 register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());62 register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());63 register(byte[].class, new ByteArrayTypeHandler());64 register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());65 register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());66 register(JdbcType.LONGVARBINARY, new BlobTypeHandler());67 register(JdbcType.BLOB, new BlobTypeHandler());68 69 register(Object.class, UNKNOWN_TYPE_HANDLER);70 register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);71 register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);72 73 register(Date.class, new DateTypeHandler());74 register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());75 register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());76 register(JdbcType.TIMESTAMP, new DateTypeHandler());77 register(JdbcType.DATE, new DateOnlyTypeHandler());78 register(JdbcType.TIME, new TimeOnlyTypeHandler());79 80 register(java.sql.Date.class, new SqlDateTypeHandler());81 register(java.sql.Time.class, new SqlTimeTypeHandler());82 register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());83 84 // issue #27385 register(Character.class, new CharacterTypeHandler());86 register(char.class, new CharacterTypeHandler());87 }
通過源碼可以發(fā)現(xiàn):MyBatis內(nèi)置注冊的類型處理器很是全面,幾乎囊括了所有常用的類型,所以一般情況下我們直接使用內(nèi)置的類型處理器進(jìn)行類型處理即可。
3.1.1 針對JavaType,MyBatis內(nèi)置注冊了一下類型:
序號 | javaType | JdbcType | TypeHandler | 入口 | 說明 |
1 | Boolean.class | null | BooleanTypeHandler | 入口2 | |
2 | boolean.class | null | BooleanTypeHandler | ||
3 | Byte.class | null | ByteTypeHandler | ||
4 | byte.class | null | ByteTypeHandler | ||
5 | Short.class | null | ShortTypeHandler | ||
6 | short.class | null | ShortTypeHandler | ||
7 | Integer.class | null | IntegerTypeHandler | ||
8 | int.class | null | IntegerTypeHandler | ||
9 | Long.class | null | LongTypeHandler | ||
10 | long.class | null | LongTypeHandler | ||
11 | Float.class | null | FloatTypeHandler | ||
12 | float.class | null | FloatTypeHandler | ||
13 | Double.class | null | DoubleTypeHandler | ||
14 | double.class | null | DoubleTypeHandler | ||
15 | String.class | null | StringTypeHandler | ||
16 | BigDecimal.class | null | BigDecimalTypeHandler | ||
17 | BigInteger.class | null | BigIntegerTypeHandler | ||
18 | Byte[].class | null | ByteObjectArrayTypeHandler | ||
19 | byte[].class | null | ByteArrayTypeHandler | ||
20 | Object.class | null | UNKNOWN_TYPE_HANDLER | ||
21 | Date.class | null | DateTypeHandler | ||
22 | java.sql.Date.class | null | SqlDateTypeHandler | ||
23 | java.sql.Time.class | null | SqlTimeTypeHandler | ||
24 | Character.class | null | CharacterTypeHandler | ||
25 | char.class | null | CharacterTypeHandler | ||
26 | java.sql.Timestamp.class | null | SqlTimestampTypeHandler |
3.1.2 針對JdbcType,MyBatis內(nèi)置注冊了一下類型:
序號 | javaType | JdbcType | TypeHandler | 入口 | 說明 |
1 | JdbcType.BOOLEAN | BooleanTypeHandler | 入口1 | ||
2 | JdbcType.BIT | BooleanTypeHandler | |||
3 | JdbcType.TINYINT | ByteTypeHandler | |||
4 | JdbcType.SMALLINT | ShortTypeHandler | |||
5 | JdbcType.INTEGER | IntegerTypeHandler | |||
6 | JdbcType.FLOAT | FloatTypeHandler | |||
7 | JdbcType.DOUBLE | DoubleTypeHandler | |||
8 | JdbcType.CHAR | StringTypeHandler | |||
9 | JdbcType.VARCHAR | StringTypeHandler | |||
10 | JdbcType.CLOB | ClobTypeHandler | |||
11 | JdbcType.LONGVARCHAR | ClobTypeHandler | |||
12 | JdbcType.NVARCHAR | NStringTypeHandler | |||
13 | JdbcType.NCHAR | NStringTypeHandler | |||
14 | JdbcType.NCLOB | NClobTypeHandler | |||
15 | dbcType.ARRAY | ArrayTypeHandler | |||
16 | JdbcType.BIGINT | LongTypeHandler | |||
17 | JdbcType.REAL | BigDecimalTypeHandler | |||
18 | JdbcType.DECIMAL | BigDecimalTypeHandler | |||
19 | JdbcType.NUMERIC | BigDecimalTypeHandler | |||
20 | JdbcType.LONGVARBINARY | BlobTypeHandler | |||
21 | JdbcType.BLOB | BlobTypeHandler | |||
22 | JdbcType.OTHER | UNKNOWN_TYPE_HANDLER | |||
23 | JdbcType.TIMESTAMP | DateTypeHandler | |||
24 | JdbcType.DATE | DateOnlyTypeHandler | |||
25 | JdbcType.TIME | TimeOnlyTypeHandler |
3.1.3 針對JdbcType和JavaType,MyBatis內(nèi)置注冊了一下類型:
序號 | JavaType | JdbcType | TypeHandler | 入口 | 說明 |
1 | Date.class | JdbcType.DATE | DateOnlyTypeHandler | 入口3 | |
2 | Date.class | JdbcType.TIME | TimeOnlyTypeHandler | ||
3 | Object.class | JdbcType.OTHER | UNKNOWN_TYPE_HANDLER | ||
4 | byte[].class | JdbcType.BLOB | BlobTypeHandler | ||
5 | byte[].class | JdbcType.LONGVARBINARY | BlobTypeHandler | ||
6 | Byte[].class | JdbcType.BLOB | BlobByteObjectArrayTypeHandler | ||
7 | Byte[].class | JdbcType.LONGVARBINARY | BlobByteObjectArrayTypeHandler | ||
8 | String.class | JdbcType.CHAR | StringTypeHandler | ||
9 | String.class | JdbcType.CLOB | ClobTypeHandler | ||
10 | String.class | JdbcType.VARCHAR | StringTypeHandler | ||
11 | String.class | JdbcType.LONGVARCHAR | ClobTypeHandler | ||
12 | String.class | JdbcType.NVARCHAR | NStringTypeHandler | ||
13 | String.class | JdbcType.NCHAR | NStringTypeHandler | ||
14 | String.class | JdbcType.NCLOB | NClobTypeHandler |
3.2 注冊入口方法
通過觀察源碼我們也可以發(fā)現(xiàn)這三種注冊方式,我在這里將這三種方式的register方法看做三個入口,分別起名為:入口1、入口2、入口3。
其中:
入口1:對應(yīng)之前介紹的第一種集合(枚舉集合),其入口方法為:
1 //入口12 public void register(JdbcType jdbcType, TypeHandler<?> handler) {3 JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);4 }
該入口方法用于將類型處理器注冊到對應(yīng)的數(shù)據(jù)庫類型。
入口2:對應(yīng)之前介紹的第二種嵌套集合(其中內(nèi)層集合的鍵為null),其入口方法為:
1 //入口22 public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {3 register((Type) javaType, typeHandler);4 }
該入口方法用于將類型處理器注冊到對應(yīng)的Java類型。
入口3:對應(yīng)之前介紹的第二種嵌套集合,其入口方法為:
1 //入口32 public <T> void register(Class<T> type, JdbcType jdbcType, TypeHandler<? extends T> handler) {3 register((Type) type, jdbcType, handler);4 }
該入口方法用于將類型處理器與Java類型和數(shù)據(jù)庫類型聯(lián)系起來。
上述的三個入口方法均是對內(nèi)而設(shè)的入口方法,也就是說是用于注冊器內(nèi)部基礎(chǔ)類型處理器(MyBatis內(nèi)置的類型處理器)注冊使用的。而MyBatis還提供了自定義類型處理器的功能,也就是說在該類中還提供了對外的自定義類型處理器注冊入口。
這么理解:對內(nèi)就是該方法被類內(nèi)部調(diào)用進(jìn)行注冊,對外就是該方法被類外部的其他類進(jìn)行調(diào)用而進(jìn)行注冊,這里的其他類其實就是XMLConfigBuilder類,它在構(gòu)建Configuration對象時就會調(diào)用對外的注冊方法,來將用戶自定義的類型處理器注冊到注冊器中。
對外入口1:只指定包名的情況下,這種情況一般需要配合注解@MappedTypes使用,使用該注解進(jìn)行JavaType的設(shè)置(即注解的value值)
1 //對外入口1:掃描器 2 public void register(String packageName) { 3 ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); 4 resolverUtil.find(new ResolverUtil.IsA(TypeHa http://www.cnblogs.com/V1haoge/p/6709157.html