mybatis源碼分析之TypeHandler

上一篇:html

mybatis源碼分析之MapperMethodjava

http://www.javashuo.com/article/p-qiqbpoee-bc.htmlsql

分析了MapperMethod從建立到執行的過程,MapperMethod的執行包括執行sql返回結果.mybatis

在執行sql和返回結果的過程當中就會涉及到參數類型的轉換,這個過程是經過TypeHandler來處理的.關於TypeHandler官網有比較詳細的文檔http://www.mybatis.org/mybatis-3/zh/configuration.html#typeHandlers,文檔主要說明了如何使用TypeHandler,在下面的分析中將重點分析與TypeHandler有關的源碼.app

1.配置

MyBatis有默認的類型處理器,若是須要自定義配置也至關簡單,在mybatis-config.xml裏添加以下配置:ide

<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

下面分析配置讀取設置的過程,在XMLConfigBuilder中源碼分析

/**
     * 讀取配置文件組裝configuration
     * @param root 配置文件的configuration節點
     */
  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

在以上源碼中有一行ui

typeHandlerElement(root.evalNode("typeHandlers"));

再來看typeHandlerElement這個方法spa

/**
   * 讀取typeHandlers配置並註冊
   * @param parent 配置文件typeHandlers節點
   * @throws Exception
   */
  private void typeHandlerElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String typeHandlerPackage = child.getStringAttribute("name");
          typeHandlerRegistry.register(typeHandlerPackage);
        } else {
          String javaTypeName = child.getStringAttribute("javaType");
          String jdbcTypeName = child.getStringAttribute("jdbcType");
          String handlerTypeName = child.getStringAttribute("handler");
          Class<?> javaTypeClass = resolveClass(javaTypeName);
          JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
          Class<?> typeHandlerClass = resolveClass(handlerTypeName);
          if (javaTypeClass != null) {
            if (jdbcType == null) {
              typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
            } else {
              typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
            }
          } else {
            typeHandlerRegistry.register(typeHandlerClass);
          }
        }
      }
    }
  }

if和else中的代碼邏輯對應了typeHandler的兩種配置方式.最後都會調用 .net

typeHandlerRegistry.register()

以上是TypeHandler與TypeHandlerRegistry,Configuration,BaseTypeHandler之間的關係.

2.設置參數

設置參數時先調用ParameterHandler.setParameters(),而後在setParameters()裏獲取相應的typeHandler,最後調用typeHandler.setParameter()

再來看看BaseTypeHandler的setParameter方法

當parameter不爲null時調用的是setNonNullParameter,也就是說子類須要實現setNonNullParameter

BigIntegerTypeHandler的源碼:

public void setNonNullParameter(PreparedStatement ps, int i, BigInteger parameter, JdbcType jdbcType) throws SQLException {
    ps.setBigDecimal(i, new BigDecimal(parameter));
  }

至此,TypeHandler的做用已經大體分析完畢了.

相關文章
相關標籤/搜索