mybatis typeHandler

typeHandler 类型转换器

在传统的JDBC中,我们需要在PreparedStatement对象中设置我们的SQL语句,在执行SQL后通过Res0ultet对象获取从数据库得到的结果。然而在Mybatis中的数据转换是通过typeHandler来实现的。其中分为jdbcType和javaType。我们的typeHandler就是负责数据库类型和java类型之间的转换。在很多时候,我们不需要去设置这些配置,mybatis会自动探测。当遇到了某些特殊情况时,就必须用自定义的typeHandler处理转换问题。
和别名一样,有系统定义的typeHandler和自定义的typeHandler。这里我们直接讨论如何自定义typeHandler。
在mybatis中typeHandler都要实现接口 org.apache.ibatis.type.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;

}
  • 其中 T是泛型,指javaType,比如我们需要String的时候,实现类可以写成 XXX implements TypeHandler。
  • setParameter方法,是通过PreparedStatement对象设置SQL参数使用的具体方法,i为在sql中参数的位置,parameter是参数,jdbcType为数据库类型。
  • 剩余的三个 getResult方法,是从JDBC结果集中获取数据进行类型转换。从结果集中获取数据分为columnName 列名方式 和 columnIndex 下标方式。最后一个是存储过程专用。

了解了接口后,通过源码得知所有的系统定义TypeHandler都实现了抽象类BaseTypeHandler。在这里我不展示BaseTypeHandle的源代码,简要的介绍一下
- BaseTypeHandle实现了接口中的方法,并尽力自动解决并将无法解决的问题作为抽象方法供继承者解决。
1. setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)方法 : 当setParameter方法中parameter和jdbcType同时为空则报出异常,仅当parameter为空时则会执行ps.setNull(i, jdbcType.TYPE_CODE);进行空设置。但当paramter不为空时,需要用户实现setNonNullParameter(ps, i, parameter, jdbcType)方法。让PreparedStatement准确的调用方法将参数设置到sql中。
2. getNullableResult(ResultSet rs, String columnName) 方法 : 是以列名方式从JDBC结果集中获取数据进行类型转换。
3. getNullableResult(ResultSet rs, int columnIndex) 方法 : 是以下标方式从JDBC结果集中获取数据进行类型转换。
4. getNullableResult(CallableStatement cs, int columnIndex)用于存储过程

接下里我们看一个例子,mybatis中String的typeHandler是怎样实现的

public class StringTypeHandler extends BaseTypeHandler<String> {

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
      throws SQLException {
    ps.setString(i, parameter);
  }

  @Override
  public String getNullableResult(ResultSet rs, String columnName)
      throws SQLException {
    return rs.getString(columnName);
  }

  @Override
  public String getNullableResult(ResultSet rs, int columnIndex)
      throws SQLException {
    return rs.getString(columnIndex);
  }

  @Override
  public String getNullableResult(CallableStatement cs, int columnIndex)
      throws SQLException {
    return cs.getString(columnIndex);
  }
}

在这里,typeHandler实现了jdbcType和javaType的相互转换。再看一下源代码中它们是如何注册的。

  public TypeHandlerRegistry() {
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());
//此后省略
}

需要注意的是自定义的类型转换是不需要注册的,一般是通过配置或扫描。
接下来我们模仿一个String的类型转换。

public class MyTypeHandler implements TypeHandler<String> {

    Logger logger = Logger.getLogger(MyTypeHandler.class);

    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter,
            JdbcType jdbcType) throws SQLException {
        logger.info("设置string参数"+parameter);
        ps.setString(i, parameter);
    }

    @Override
    public String getResult(ResultSet rs, String columnName)
            throws SQLException {
        String result = rs.getString(columnName);
        logger.info("读取String columnName参数"+result);
        return result;
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        String result = rs.getString(columnIndex);
        logger.info("读取String columnIndex参数"+result);
        return result;
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        String result = cs.getString(columnIndex);
        logger.info("cs 读取String columnIndex参数"+result);
        return result;
    }


}

接下来我们需要配置启用刚刚的typeHandler,然后就可以测试了。

<typeHandlers>
        <typeHandler javaType="string" jdbcType="VARCHAR" handler="lly.mybatis.example.utils.MyTypeHandler"/>
    </typeHandlers>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值