MyBatis整合Spring的實現(5)

分析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這裏的設計理念。

注:類型也支持註解方式,做者沒有使用過註解,也就沒有分析關於註解方式。

相關文章
相關標籤/搜索