原創(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)造器源碼羅列:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 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   }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

  通過源碼可以發(fā)現(xiàn):MyBatis內(nèi)置注冊的類型處理器很是全面,幾乎囊括了所有常用的類型,所以一般情況下我們直接使用內(nèi)置的類型處理器進(jìn)行類型處理即可。

3.1.1 針對JavaType,MyBatis內(nèi)置注冊了一下類型:

序號javaTypeJdbcTypeTypeHandler入口說明
1Boolean.classnullBooleanTypeHandler入口2
2boolean.classnullBooleanTypeHandler
3Byte.classnullByteTypeHandler
4byte.classnullByteTypeHandler
5Short.classnullShortTypeHandler
6short.classnullShortTypeHandler
7Integer.classnullIntegerTypeHandler
8int.classnullIntegerTypeHandler
9Long.classnullLongTypeHandler
10long.classnullLongTypeHandler
11Float.classnullFloatTypeHandler
12float.classnullFloatTypeHandler
13Double.classnullDoubleTypeHandler
14double.classnullDoubleTypeHandler
15String.classnullStringTypeHandler
16BigDecimal.classnullBigDecimalTypeHandler
17BigInteger.classnullBigIntegerTypeHandler
18Byte[].classnullByteObjectArrayTypeHandler
19byte[].classnullByteArrayTypeHandler
20Object.classnullUNKNOWN_TYPE_HANDLER
21Date.classnullDateTypeHandler
22java.sql.Date.classnullSqlDateTypeHandler
23java.sql.Time.classnullSqlTimeTypeHandler
24Character.classnullCharacterTypeHandler
25char.classnullCharacterTypeHandler
26java.sql.Timestamp.classnullSqlTimestampTypeHandler

3.1.2 針對JdbcType,MyBatis內(nèi)置注冊了一下類型:

序號javaTypeJdbcTypeTypeHandler入口說明
1
JdbcType.BOOLEANBooleanTypeHandler入口1
2
JdbcType.BITBooleanTypeHandler
3
JdbcType.TINYINTByteTypeHandler
4
JdbcType.SMALLINTShortTypeHandler
5
JdbcType.INTEGERIntegerTypeHandler
6
JdbcType.FLOATFloatTypeHandler
7
JdbcType.DOUBLEDoubleTypeHandler
8
JdbcType.CHARStringTypeHandler
9
JdbcType.VARCHARStringTypeHandler
10
JdbcType.CLOBClobTypeHandler
11
JdbcType.LONGVARCHARClobTypeHandler
12
JdbcType.NVARCHARNStringTypeHandler
13
JdbcType.NCHARNStringTypeHandler
14
JdbcType.NCLOBNClobTypeHandler
15
dbcType.ARRAYArrayTypeHandler
16
JdbcType.BIGINTLongTypeHandler
17
JdbcType.REALBigDecimalTypeHandler
18
JdbcType.DECIMALBigDecimalTypeHandler
19
JdbcType.NUMERICBigDecimalTypeHandler
20
JdbcType.LONGVARBINARYBlobTypeHandler
21
JdbcType.BLOBBlobTypeHandler
22
JdbcType.OTHERUNKNOWN_TYPE_HANDLER
23
JdbcType.TIMESTAMPDateTypeHandler
24
JdbcType.DATEDateOnlyTypeHandler
25
JdbcType.TIMETimeOnlyTypeHandler

3.1.3 針對JdbcType和JavaType,MyBatis內(nèi)置注冊了一下類型:

序號JavaTypeJdbcTypeTypeHandler入口說明
1Date.classJdbcType.DATEDateOnlyTypeHandler入口3
2Date.classJdbcType.TIMETimeOnlyTypeHandler
3Object.classJdbcType.OTHERUNKNOWN_TYPE_HANDLER
4byte[].classJdbcType.BLOBBlobTypeHandler
5byte[].classJdbcType.LONGVARBINARYBlobTypeHandler
6Byte[].classJdbcType.BLOBBlobByteObjectArrayTypeHandler
7Byte[].classJdbcType.LONGVARBINARYBlobByteObjectArrayTypeHandler
8String.classJdbcType.CHARStringTypeHandler
9String.classJdbcType.CLOBClobTypeHandler
10String.classJdbcType.VARCHARStringTypeHandler
11String.classJdbcType.LONGVARCHARClobTypeHandler
12String.classJdbcType.NVARCHARNStringTypeHandler
13String.classJdbcType.NCHARNStringTypeHandler
14String.classJdbcType.NCLOBNClobTypeHandler

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值)

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 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