分析java
MyBatis整合Spring的實現(1)中代碼實現的4.4攔截器後面文章根據具體例子分析,分析4.五、4.6能夠知道,這2個都是去生成類型管理器TypeHandlerRegistry類,下面就來分析代碼。數據庫
1 屬性測試
這裏的屬性都是定義基本的類型,因此咱們針對每一個Map屬性,挑選出一條來進行分析。this
1.1 reversePrimitiveMapspa
private static final Map<Class<?>, Class<?>> reversePrimitiveMap = new HashMap<Class<?>, Class<?>>(){ private static final long serialVersionUID = 1L; { put(Byte.class, byte.class); put(Short.class, short.class); put(Integer.class, int.class); put(Long.class, long.class); put(Float.class, float.class); put(Double.class, double.class); put(Boolean.class, boolean.class); put(Character.class, char.class); } };
首先是原始類型的對象對應原始類型的Class。.net
1.2 JDBC類型對應的類型處理器------JDBC_TYPE_HANDLER_MAPdebug
private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class); register(JdbcType.CHAR, new StringTypeHandler());
上面就是數據庫中CHAR類型,對應StringTypeHandler處理器。設計
1.3 JAVA類型、數據庫類型、處理器對應MAP------TYPE_HANDLER_MAPcode
private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>(); register(String.class, JdbcType.CHAR, new StringTypeHandler()); private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) { if (javaType != null) { Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType); if (map == null) { map = new HashMap<JdbcType, TypeHandler<?>>(); TYPE_HANDLER_MAP.put(javaType, map); } map.put(jdbcType, handler); if (reversePrimitiveMap.containsKey(javaType)) { register(reversePrimitiveMap.get(javaType), jdbcType, handler); } } ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler); }
上面就是JAVA類型爲String,數據庫類型爲CHAR,對應StringTypeHandler處理器。orm
1.4 未知處理類型------UNKNOWN_TYPE_HANDLER
private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this); register(Object.class, UNKNOWN_TYPE_HANDLER); register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER); register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
未知類型處理比較少,就所有列出來,也就是最大範圍,Object是全部類的父類。
1.5 處理器自己------ALL_TYPE_HANDLERS_MAP
private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();
本文1.3就已經有這部分代碼的處理,把處理器的Class做爲Map的key,value爲處理器自己。
2 類型處理器做用------StringTypeHandler
處理器有不少,這裏只選擇一個來進行分析。
2.1 父類BaseTypeHandler
上圖是父類BaseTypeHandler,使用了泛型,並繼承TypeReference,實現TypeHandler。
2.2 接口TypeHandler
寫過底層JDBC代碼的朋友都清楚,這幾個方法是作什麼的。
2.2.1 setParameter
當JAVA代碼中使用PreparedStatement時,由於是預編譯,因此值是後來設置的,這個方法就是對相應的?設置值。
2.2.2 T getResult(ResultSet rs, String columnName)
方法是經過最後的列名獲取相應的列的值。
2.2.3 T getResult(ResultSet rs, int columnIndex)
方法是經過順序獲取相應的列的值。
2.2.4 T getResult(CallableStatement cs, int columnIndex)
方法是存儲過程調用返回的結果,也是經過順序獲取相應的列的值。
2.3 TypeReference
不清楚,之後再補充。。。
3 類型管理器,Spring配置屬性------包/類
if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray) { configuration.getTypeHandlerRegistry().register(packageToScan); if (this.logger.isDebugEnabled()) { this.logger.debug("Scanned package: '" + packageToScan + "' for type handlers"); } } } if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (this.logger.isDebugEnabled()) { this.logger.debug("Registered type handler: '" + typeHandler + "'"); } } }
根據前一章,這裏很好分析,代碼作了哪些事情。這裏再也不過多的分析。
總結:
類型處理器的做用,就是在SQL設置值(PreparedStatement)時,把JAVA類型的對象轉換成數據庫類型。
在SQL執行結果返回時,把數據庫類型的數據轉換成JAVA類型對象。
實際應用中,默認的類型處理器基本已經夠用。
這裏只是針對字符串類型進行分析,其它類型也都同樣,能夠自行看看源碼。若是對JDBC不太清楚,能夠找找資料,寫個測試類,看看JDBC代碼。能更好的瞭解,MyBatis這裏的設計理念。
注:類型也支持註解方式,做者沒有使用過註解,也就沒有分析關於註解方式。