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