写点什么

聊聊 Mybatis 的类型转换接口 TypeHandler

作者:周杰伦本人
  • 2022-11-24
    山东
  • 本文字数:1852 字

    阅读完需:约 6 分钟

聊聊 Mybatis 的类型转换接口 TypeHandler

mybatis 可以实现 jdbc 类型和 java 类型之间的转换,具体来说有一个类型转换器的接口:

类型处理器接口 TypeHandler

TypeHandler 接口的定义如下:


public interface TypeHandler<T> {
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
复制代码


接口中定义了设置参数的方法和获取结果的方法,根据参数不同定义了三种获取结果的方法,这是 Java 多态的体现,而接口的定义和方法的定义都使用了泛型。

类型处理器 BaseTypeHandler

jdbc 类型转为 java 类型

BaseTypeHandler 类实现了 TypeHandler 接口,实现了 setParameter()方法


这是 BaseTypeHandler 类的 setParameter()方法的实现逻辑:


@Override  public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {    if (parameter == null) {      if (jdbcType == null) {        throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");      }      try {        ps.setNull(i, jdbcType.TYPE_CODE);      } catch (SQLException e) {        throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "              + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "              + "Cause: " + e, e);      }    } else {      try {        setNonNullParameter(ps, i, parameter, jdbcType);      } catch (Exception e) {        throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "              + "Try setting a different JdbcType for this parameter or a different configuration property. "              + "Cause: " + e, e);      }    }  }
复制代码


这个方法看着很长,其实逻辑非常的简单,方法中就是设置 PreparedStatement 的参数,也是参数绑定,将 jdbcType 转为 Java 类型,setNonNullParameter 是抽象方法,根据不同的参数类型有不同的类实现了这个方法,比如 LongTypeHandler 实现的 setNonNullParameter()方法:


@Override  public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType)      throws SQLException {    ps.setLong(i, parameter);  }
复制代码

java 类型转为 jdbc 类型

BaseTypeHandler 类作为 TypeHandler 接口的基础实现类,它同样实现了获取转换后的结果的方法。BaseTypeHandler 类的 getResult()方法:


@Override  public T getResult(CallableStatement cs, int columnIndex) throws SQLException {    try {      return getNullableResult(cs, columnIndex);    } catch (Exception e) {      throw new ResultMapException("Error attempting to get column #" + columnIndex + " from callable statement.  Cause: " + e, e);    }  }
复制代码


方法也比较简单,直接调用了 getNullableResult 抽象类,功能就是从 ResultSet 中获取数据,把 Java 类型转换为 JdbcType 类型,比如 LongTypeHandler 实现的 getNullableResult():


@Override  public Long getNullableResult(ResultSet rs, String columnName)      throws SQLException {    long result = rs.getLong(columnName);    return result == 0 && rs.wasNull() ? null : result;  }
复制代码


这一块的逻辑和设置参数的方法整体逻辑是差不多的,整体思想有种模板方法设计模式的设计思想


通过源码分析我们知道了 TypeHandler 接口的作用就是用来实现类型转换的,mybatis 在初始化的时候就获取 TypeHandler,然后创建 TypeHandler 实例注册到 TypeHandlerRegistry 中,由 TypeHandlerRegistry 来进行管理这些实例,下篇文章中我们介绍一下 TypeHandlerRegistry 这个类

总结

这篇文章讲了 Mybatis 的类型转换接口 TypeHandler 和它的实现类 BaseTypeHandler,类型转换接口显然就是实现 jdbc 类型和 java 类型之间的转换,同时分析了 BaseTypeHandler 的 setParameter()方法和 getResult()方法,getNullableResult 是抽象类,具体方法由其他实现类进行实现。

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2020-02-29 加入

公众号《周结论本人》,多平台优质博主

评论

发布
暂无评论
聊聊Mybatis的类型转换接口TypeHandler_11月月更_周杰伦本人_InfoQ写作社区