Mybatis类型转换介绍


 

 

  在Mybatis中可以定义一个TypeHandler类型,通过它可以实现Java类型跟数据库类型的相互转换。 

TypeHandler接口

       在Mybatis中要实现自己的TypeHandler就需要实现Mybatis为提供的TypeHandler接口。在TypeHandler中定义了四个方法:

public interface TypeHandler<T> {
 
    /**
     * 用于定义在Mybatis设置参数时,该如何把Java类型的参数转换为对应的数据库类型
     * @param ps 当前的PreparedStatement对象
     * @param i  当前参数的位置
     * @param parameter 当前参数的Java对象
     * @param jdbcType  当前参数的数据库类型
     * @throws SQLException
     */
    void setParameter(PreparedStatement ps, int i, T parameter,JdbcType jdbcType) throws SQLException;
 
    /**
     * 用于在Mybatis获取数据结果集时,如何把数据库类型转换为对应的Java类型
     * @param rs 当前的结果集
     * @param columnName 当前的字段名称
     * @return 转换后的Java对象
     * @throws SQLException
     */
    T getResult(ResultSet rs, String columnName) throws SQLException;
 
    /**
     * 用于在Mybatis通过字段位置获取字段数据时,把数据库类型转换为对应的Java类型
     * @param rs 当前的结果集
     * @param columnIndex 当前字段的位置
     * @return 转换后的Java对象
     * @throws SQLException
     */
    T getResult(ResultSet rs, int columnIndex) throws SQLException;
 
    /**
     * 用于Mybatis在调用存储过程后,把数据库类型的数据转换为对应的Java类型
     * @param cs 当前的CallableStatement执行后的CallableStatement
     * @param columnIndex 当前输出参数的位置
     * @return
     * @throws SQLException
     */
    T getResult(CallableStatement cs, int columnIndex) throws SQLException;
 
}

  Mybatis还为我们提供一个实现了TypeHandler接口的抽象类BaseTypeHandler。所以我们也可以通过继承BaseTypeHandler来实现自己的TypeHandler。

       先来看一下BaseTypeHandler类的定义:

public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
 
  protected Configuration configuration;
 
  public void setConfiguration(Configuration c) {
    this.configuration = c;
  }
 
  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 {
      setNonNullParameter(ps, i, parameter, jdbcType);
    }
  }
 
  public T getResult(ResultSet rs, String columnName) throws SQLException {
    T result = getNullableResult(rs, columnName);
    if (rs.wasNull()) {
      return null;
    } else {
      return result;
    }
  }
 
  public T getResult(ResultSet rs, int columnIndex) throws SQLException {
    T result = getNullableResult(rs, columnIndex);
    if (rs.wasNull()) {
      return null;
    } else {
      return result;
    }
  }
 
  public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
    T result = getNullableResult(cs, columnIndex);
    if (cs.wasNull()) {
      return null;
    } else {
      return result;
    }
  }
 
  public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
 
  public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
 
  public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
 
  public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
 
}

案例

  向数据库写数据,要写的是一个Date对象,但是写到数据库之后,这个Date对象就变成了Date对象所描述的时间到1970年的秒数,然后当从数据库读取这个秒数之后,系统又会自动帮我将这个秒数转为Date对象。

  创建一张User表

     user实例

public class User {
    private Long id;
    private String username;
    private String password;
    private Date regTime;
    ....

在定义TypeHandler对象

package mybatis.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Date.class)
public class MyTypeHandler extends BaseTypeHandler<Date> {

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

    @Override
    public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return new Date(rs.getLong(columnName));//以long的数据类型形式读取内容
    }

    @Override
    public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return new Date(rs.getLong(columnIndex));
    }

    @Override
    public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getDate(columnIndex);
    }
}
1.@MappedJdbcTypes定义是JdbcType类型,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型
2.@MappedTypes定义的是JavaType的数据类型,描述哪些Java类型可被拦截3.在我们启用了自定义的这个TypeHandler之后,数据的读写都会被这个类所过滤 4.在setNonNullParameter方法中,重新定义要写往数据库的数据。 
5.在另外三个方法中我们将从数据库读出的数据类型进行转换。

  在配置文件中注册自定义的handler

  mybatis配置文件中注册typeHandler,注册有两种不同的方式:1、直接注册一个包中所有的typeHandler,系统在启动时会自动扫描包下的所有文件  2、一个类一个类的注册

  <!--需要在别名标签之后-->
  <typeHandlers>
        <typeHandler handler="mybatis.handler.MyTypeHandler"/>
    </typeHandlers>

or

  <typeHandlers>
        <package name="mybatis.handler"/>
    </typeHandlers>

  在Mapper中配置

   <resultMap id="userResult" type="user">
        <result typeHandler="mybatis.handler.MyTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"
                property="regTime" column="regTime"/>
   </resultMap>

  select中使用这个resultMap:

   <select id="getUser" parameterType="Integer" resultMap="userResult">
        select * from user where id=#{id}
    </select>

  想要在插入的时候,启用自定义的typeHandler,除了在mybatis配置文件中配置的方法,也可以insert节点中简单配置一下,如下:

  <insert id="insertUser" parameterType="org.sang.bean.User">
        INSERT INTO user(username,password,regTime) 
VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR,typeHandler=mybatis.handler.MyDateTypeHandler})
</insert>

  插入结果:

  读出结果

  总结就是读取时的配置要和插入时的配置分开,读取时数据转换,有两种配置方式,分别是resultMap和在mybatis配置文件中配置typeHandlers,插入时的配置就是在insert节点中进行配置。

 

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM