Mybatis基础-类型转换模块

Java程序<-->数据库,javaType<-->jdbcType,Mybatis使用类型处理器完成上述转换。

一、TypeHandler

TypeHandler是类型转换器,BaseTypeHandler是抽象基类,用于实现javaType和jdbcType的转换,有众多的实现类。主要方法是设置参数和获取查询结果集,底层实现还是基于PrepareStatement、ResultSet。TypeHandler可以通过mybatis-config配置文件typeHandler节点自定义。

设置参数值:

  //BaseTypeHandler类  
  @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);
      }
    }
  }

  //StringTypeHandler继承了BaseTypeHandler类
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
      throws SQLException {
    //本质还是调用PreparedStatement的设置值的方法
    ps.setString(i, parameter);
  }

获取结果集:

  @Override
  public T getResult(ResultSet rs, String columnName) throws SQLException {
    try {
      return getNullableResult(rs, columnName);
    } catch (Exception e) {
      throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + e, e);
    }
  }

  //IntegerTypeHandler继承了BaseTypeHandler
  @Override
  public Integer getNullableResult(ResultSet rs, String columnName)
      throws SQLException {
    //本质还是调用了ResultSet方法
    int result = rs.getInt(columnName);
    return result == 0 && rs.wasNull() ? null : result;
  }

二、TypeHandlerRegistry

mybatis如何管理众多的TypeHandler实现类呢,TypeHandlerRegistry就是TypeHandler的管理者,它决定着在何时选择何种实现类完成类型转换工作。TypeHandler实现类在mybatis初始化时注册到了TypeHandlerRegistry中。

  //MybatisAutoConfiguration中创建Configuration对象时创建的TypeHandlerRegistry对象
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    //...
    Configuration configuration = this.properties.getConfiguration();
    if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
       //创建Configuration对象
      configuration = new Configuration();
    }
    //...
   }

   //Configuration类
  protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
  protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
    

  //TypeHandlerRegistry类
  private final Map<JdbcType, TypeHandler<?>>  jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);
    //key为javaType
  private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
    
  //在构造方法中注册类型转换器
  public TypeHandlerRegistry() {
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());

    register(Byte.class, new ByteTypeHandler());
    register(byte.class, new ByteTypeHandler());
    register(JdbcType.TINYINT, new ByteTypeHandler());

    register(Short.class, new ShortTypeHandler());
    register(short.class, new ShortTypeHandler());
    register(JdbcType.SMALLINT, new ShortTypeHandler());
    //...
 }

三、TypeAliasRegistry

指定别名,mybatis默认指定了一些别名,也可以通过配置文件自定义别名。

  public TypeAliasRegistry() {
    registerAlias("string", String.class);

    registerAlias("byte", Byte.class);
    registerAlias("long", Long.class);
    registerAlias("short", Short.class);
    registerAlias("int", Integer.class);
    registerAlias("integer", Integer.class);
    registerAlias("double", Double.class);
    registerAlias("float", Float.class);
    registerAlias("boolean", Boolean.class);
    //...
  }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值