TypeHandler for mybatis source code analysis

Previous:

MapperMethod of mybatis source code analysis

https://my.oschina.net/u/657390/blog/755787

The process of MapperMethod from creation to execution is analyzed, and the execution of MapperMethod includes executing sql to return results.

The conversion of parameter types is involved in the process of executing sql and returning results. This process is handled by TypeHandler. There are more detailed documents on the official website of TypeHandler http://www.mybatis.org/mybatis-3/zh /configuration.html#typeHandlers, the document mainly explains how to use TypeHandler. In the following analysis, the source code related to TypeHandler will be analyzed.

1. Configuration

MyBatis has a default type processor. If you need to customize the configuration, it is quite simple. Add the following configuration to mybatis-config.xml:

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

The following analyzes the process of configuring read settings, in 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);
    }
  }

In the above source code there is a line

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

Let's look at the method of typeHandlerElement

/**
   * 读取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);
          }
        }
      }
    }
  }

The code logic in if and else corresponds to the two configuration methods of typeHandler. In the end, it will be called 

typeHandlerRegistry.register()

The above is the relationship between TypeHandler and TypeHandlerRegistry, Configuration, BaseTypeHandler.

2. Set parameters

When setting parameters, first call ParameterHandler.setParameters(), then get the corresponding typeHandler in setParameters(), and finally call typeHandler.setParameter()

Let's take a look at the setParameter method of BaseTypeHandler

When the parameter is not null, setNonNullParameter is called, that is to say, the subclass needs to implement setNonNullParameter

Source code of BigIntegerTypeHandler:

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

So far, the role of TypeHandler has been roughly analyzed.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325457727&siteId=291194637