欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

微服務(wù)mybatis?typehandler使用詳解(就這一篇夠了)

 更新時(shí)間:2024年10月11日 12:04:27   作者:Crystalqy  
TypeHandler是MyBatis框架的核心組件,實(shí)現(xiàn)數(shù)據(jù)庫(kù)表字段類型和Java?數(shù)據(jù)類型之間的相互轉(zhuǎn)換,本文介紹通過(guò)實(shí)例代碼mybatis?typehandler使用,感興趣的朋友一起看看吧

Mybatis TypeHandler類型轉(zhuǎn)換器是負(fù)責(zé)Java類和jdbc類型之間的轉(zhuǎn)換

主要涉及到下面這幾個(gè)類:

  • TypeHandler 類型轉(zhuǎn)換器的頂層接口
  • BaseTypeHandler 抽象類繼承自TypeHandlerMybatis中所有的類型轉(zhuǎn)換器實(shí)現(xiàn)均繼承他。
  • TypeHandlerRegistry 類型轉(zhuǎn)換器注冊(cè)器,負(fù)責(zé)存儲(chǔ)類型轉(zhuǎn)換器。
  • TypeAliasRegistry 類型別名轉(zhuǎn)換器,用來(lái)存儲(chǔ)類型與別名的對(duì)應(yīng)關(guān)系。

1 TypeHandler

TypeHandler是類型轉(zhuǎn)換器的頂層接口,其定義了類型轉(zhuǎn)換器應(yīng)該具有的功能,

TypeHandler主要解決了兩個(gè)問(wèn)題:

  1. 可以指定我們?cè)贘ava實(shí)體類所包含的自定義類型存入數(shù)據(jù)庫(kù)后的類型是什么
  2. 從數(shù)據(jù)庫(kù)中取出該數(shù)據(jù)后自動(dòng)轉(zhuǎn)換為我們自定義的Java類型

其源碼如下:

public interface TypeHandler<T> {  
   
    /** 
     * 用于定義在Mybatis設(shè)置參數(shù)時(shí)該如何把Java類型的參數(shù)轉(zhuǎn)換為對(duì)應(yīng)的數(shù)據(jù)庫(kù)類型 
     * @param ps 當(dāng)前的PreparedStatement對(duì)象 
     * @param i 當(dāng)前參數(shù)的位置 
     * @param parameter 當(dāng)前參數(shù)的Java對(duì)象 
     * @param jdbcType 當(dāng)前參數(shù)的數(shù)據(jù)庫(kù)類型 
     * @throws SQLException 
     */  
    void setParameter(PreparedStatement ps, int i, T parameter,  
           JdbcType jdbcType) throws SQLException;  
   
    /** 
     * 用于在Mybatis獲取數(shù)據(jù)結(jié)果集時(shí)如何把數(shù)據(jù)庫(kù)類型轉(zhuǎn)換為對(duì)應(yīng)的Java類型 
     * @param rs 當(dāng)前的結(jié)果集 
     * @param columnName 當(dāng)前的字段名稱 
     * @return 轉(zhuǎn)換后的Java對(duì)象 
     * @throws SQLException 
     */  
    T getResult(ResultSet rs, String columnName) throws SQLException;  
   
    /** 
     * 用于在Mybatis通過(guò)字段位置獲取字段數(shù)據(jù)時(shí)把數(shù)據(jù)庫(kù)類型轉(zhuǎn)換為對(duì)應(yīng)的Java類型 
     * @param rs 當(dāng)前的結(jié)果集 
     * @param columnIndex 當(dāng)前字段的位置 
     * @return 轉(zhuǎn)換后的Java對(duì)象 
     * @throws SQLException 
     */  
    T getResult(ResultSet rs, int columnIndex) throws SQLException;  
   
    /** 
     * 用于Mybatis在調(diào)用存儲(chǔ)過(guò)程后把數(shù)據(jù)庫(kù)類型的數(shù)據(jù)轉(zhuǎn)換為對(duì)應(yīng)的Java類型 
     * @param cs 當(dāng)前的CallableStatement執(zhí)行后的CallableStatement 
     * @param columnIndex 當(dāng)前輸出參數(shù)的位置 
     * @return 
     * @throws SQLException 
     */  
    T getResult(CallableStatement cs, int columnIndex) throws SQLException;  
   
}  

2 BaseTypeHandler

BaseTypeHandler是一個(gè)抽象類,改類實(shí)現(xiàn)了TypeHandler中的方法并實(shí)現(xiàn)了異常捕獲。繼承改類我們可以很容易的實(shí)現(xiàn)一個(gè)自定義類型轉(zhuǎn)換器,其源碼如下:

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;  
   
}  

我們可以看到BaseTypeHandler對(duì)TypeHandler接口的四個(gè)方法做了一個(gè)簡(jiǎn)單的選擇,把null值的情況都做了一個(gè)過(guò)濾,核心的取值和設(shè)值的方法還是抽象出來(lái)了供子類來(lái)實(shí)現(xiàn)。使用BaseTypeHandler還有一個(gè)好處是它繼承了另外一個(gè)叫做TypeReference的抽象類,通過(guò)TypeReference的getRawType()方法可以獲取到當(dāng)前TypeHandler所使用泛型的原始類型。這對(duì)Mybatis在注冊(cè)TypeHandler的時(shí)候是非常有好處的。在沒(méi)有指定javaType的情況下,Mybatis在注冊(cè)TypeHandler時(shí)可以通過(guò)它來(lái)獲取當(dāng)前TypeHandler所使用泛型的原始類型作為要注冊(cè)的TypeHandler的javaType類型,這個(gè)在講到Mybatis注冊(cè)TypeHandler的方式時(shí)將講到。

3 注冊(cè)TypeHandler

為什么Java自帶的類型在存取的時(shí)候不會(huì)出錯(cuò),我們自定義的類型就會(huì)出錯(cuò)?那是因?yàn)閙ybatis已經(jīng)將這些類型的TypeHandler提前寫好了,并且注冊(cè)好了

具體注冊(cè)了哪些,我們可以看TypeHandlerRegistry這個(gè)類:

public TypeHandlerRegistry(Configuration configuration) {
    this.unknownTypeHandler = new UnknownTypeHandler(configuration);
 
    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());
 
    register(Integer.class, new IntegerTypeHandler());
    register(int.class, new IntegerTypeHandler());
    register(JdbcType.INTEGER, new IntegerTypeHandler());
 
    register(Long.class, new LongTypeHandler());
    register(long.class, new LongTypeHandler());
 
    register(Float.class, new FloatTypeHandler());
    register(float.class, new FloatTypeHandler());
    register(JdbcType.FLOAT, new FloatTypeHandler());
 
    register(Double.class, new DoubleTypeHandler());
    register(double.class, new DoubleTypeHandler());
    register(JdbcType.DOUBLE, new DoubleTypeHandler());
 
    register(Reader.class, new ClobReaderTypeHandler());
    register(String.class, new StringTypeHandler());
    register(String.class, JdbcType.CHAR, new StringTypeHandler());
    register(String.class, JdbcType.CLOB, new ClobTypeHandler());
    register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
    register(JdbcType.CHAR, new StringTypeHandler());
    register(JdbcType.VARCHAR, new StringTypeHandler());
    register(JdbcType.CLOB, new ClobTypeHandler());
    register(JdbcType.LONGVARCHAR, new StringTypeHandler());
    register(JdbcType.NVARCHAR, new NStringTypeHandler());
    register(JdbcType.NCHAR, new NStringTypeHandler());
    register(JdbcType.NCLOB, new NClobTypeHandler());
 
    register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
    register(JdbcType.ARRAY, new ArrayTypeHandler());
 
    register(BigInteger.class, new BigIntegerTypeHandler());
    register(JdbcType.BIGINT, new LongTypeHandler());
 
    register(BigDecimal.class, new BigDecimalTypeHandler());
    register(JdbcType.REAL, new BigDecimalTypeHandler());
    register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
    register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
 
    register(InputStream.class, new BlobInputStreamTypeHandler());
    register(Byte[].class, new ByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
    register(byte[].class, new ByteArrayTypeHandler());
    register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
    register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.BLOB, new BlobTypeHandler());
 
    register(Object.class, unknownTypeHandler);
    register(Object.class, JdbcType.OTHER, unknownTypeHandler);
    register(JdbcType.OTHER, unknownTypeHandler);
 
    register(Date.class, new DateTypeHandler());
    register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
    register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
    register(JdbcType.TIMESTAMP, new DateTypeHandler());
    register(JdbcType.DATE, new DateOnlyTypeHandler());
    register(JdbcType.TIME, new TimeOnlyTypeHandler());
 
    register(java.sql.Date.class, new SqlDateTypeHandler());
    register(java.sql.Time.class, new SqlTimeTypeHandler());
    register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
 
    register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());
 
    register(Instant.class, new InstantTypeHandler());
    register(LocalDateTime.class, new LocalDateTimeTypeHandler());
    register(LocalDate.class, new LocalDateTypeHandler());
    register(LocalTime.class, new LocalTimeTypeHandler());
    register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
    register(OffsetTime.class, new OffsetTimeTypeHandler());
    register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
    register(Month.class, new MonthTypeHandler());
    register(Year.class, new YearTypeHandler());
    register(YearMonth.class, new YearMonthTypeHandler());
    register(JapaneseDate.class, new JapaneseDateTypeHandler());
 
    // issue #273
    register(Character.class, new CharacterTypeHandler());
    register(char.class, new CharacterTypeHandler());
  }

4. 實(shí)現(xiàn)自定義的TypeHandler

我們可以直接繼承BaseTypeHandler來(lái)實(shí)現(xiàn)我們自己的類型轉(zhuǎn)換器

我們要實(shí)現(xiàn)把json字符串轉(zhuǎn)換成為我們的對(duì)象,可以這么實(shí)現(xiàn):

public class JsonTypeHandler<T> extends BaseTypeHandler<T> {
	
    private final Class<T> type;
 
    public JsonTypeHandler(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("輸入?yún)?shù)不能為空");
        }
        this.type = type;
    }
 
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)
            throws SQLException {
        try {
        	String json = JsonUtil.toJson(parameter);
            ps.setString(i, json);
        } catch (Exception e) {
            throw new RuntimeException("Json對(duì)象轉(zhuǎn)換成String失敗", e);
        }
    }
 
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return convertJsonToObject(json);
    }
 
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return convertJsonToObject(json);
    }
 
    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return convertJsonToObject(json);
    }
 
    private T convertJsonToObject(String json) {
        try {
            return JsonUtil.fromJson(json, type);
        } catch (Exception e) {
            throw new RuntimeException("json轉(zhuǎn)換成Java對(duì)象失敗", e);
        }
    }
}

因?yàn)槲覀兪褂玫氖荢pring boot工程,只需要把JsonTypeHandler放到Spring boot可以掃描的目錄下即可。

在XML中使用:

<resultMap id="BaseResultMap" type="com.db.model.SettlementBill">
	    <id column="id" jdbcType="INTEGER" property="id" />
	    <result column="receipts_code" jdbcType="VARCHAR" property="receiptsCode" />
	    <result column="finance_info" jdbcType="VARCHAR"  property="financeDetailVO1" 
		     javaType="com.db.model.SettlementBill"
		     typeHandler="com.mybatis.handler.JsonArrayTypeHandler" 
	     />
	</resultMap>
  
  
  <select id="test" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select  id, receipts_code, finance_info from settlement_bill where id = #{id,jdbcType=INTEGER}
  </select>

Mybatis Plus中的使用方式:

@TableName(value = "settlement_bill", autoResultMap = true)
@Data
public class SettlementBill extends CxmBaseModel implements Serializable {
	@TableId(value = "id", type = IdType.AUTO)
	private Integer id;
	
	@TableField(value = "finance_info",typeHandler = JsonTypeHandler.class)
    private BatchFinanceDetailVO1 financeDetailVO1;
}

5. Mybatis自動(dòng)獲取TypeHandle

在介紹了Mybatis是如何注冊(cè)TypeHandler之后就介紹一下Mybatis是如何獲取對(duì)應(yīng)的TypeHandler進(jìn)行類型轉(zhuǎn)換的。

如果我們?cè)贛apper.xml文件中配置某一個(gè)屬性或變量的映射關(guān)系時(shí)指定了該屬性對(duì)應(yīng)的javaType和jdbcType,則Mybatis會(huì)從注冊(cè)好的TypeHandler中尋找對(duì)應(yīng)的javaType和jdbcType組合的TypeHandler進(jìn)行處理,這也是Mybatis最基本的獲取TypeHandler進(jìn)行類型轉(zhuǎn)換的方式。

1.javaType和jdbcType都指定

假設(shè)Mybatis配置文件中有這么一段TypeHandler的注冊(cè)信息:

<typeHandlers>  
   <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>  
</typeHandlers>  

看這樣一個(gè)UserMapper.xml定義:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
   
<mapper namespace="com.tiantian.mybatis.mapper.UserMapper">  
   
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>  
    </resultMap>  
   
    <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyColumn="id">  
       insert into t_user(name, age, interests) values(#{name}, #{age}, #{interests, javaType=[Ljava.lang.String;, jdbcType=VARCHAR})  
    </insert>  
     
    <update id="updateUser" parameterType="User">  
       update t_user set name=#{name}, age=#{age}, interests=#{interests} where id=#{id}  
    </update>  
     
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
     
    <delete id="deleteUser" parameterType="int">  
       delete from t_user where id=#{id}  
    </delete>  
</mapper>  

我們可以看到在id為UserResult的resultMap中,我們定義了一個(gè)對(duì)應(yīng)字段interests的映射關(guān)系,并且定義了其javaType為“[Ljava.lang.String;”,jdbcType為VARCHAR,這個(gè)時(shí)候Mybatis就會(huì)到已經(jīng)注冊(cè)了的TypeHandler中尋找到能處理javaType和jdbcType對(duì)應(yīng)的類型轉(zhuǎn)換的TypeHandler來(lái)進(jìn)行處理。在這里就會(huì)找到我們注冊(cè)的StringArrayTypeHandler。在上面id為insertUser的insert語(yǔ)句中,我們也為變量interests指定了它的javaType和jdbcType屬性,這時(shí)候Mybatis也會(huì)尋找javaType和jdbcType對(duì)應(yīng)的TypeHandler。上面這樣定義是Mybatis最基本也是最完整地獲取到對(duì)應(yīng)的TypeHandler的方法。

2. 只指定變量對(duì)應(yīng)的javaType類型。

這個(gè)時(shí)候Mybatis會(huì)拿著這個(gè)javaType和jdbcType為null的組合到注冊(cè)的TypeHandler中尋找對(duì)應(yīng)的TypeHandler。

(1)不動(dòng)StringArrayTypeHandler的注冊(cè)信息,把我們的UserMapper.xml改為如下形式:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" javaType="[Ljava.lang.String;"/>  
    </resultMap>  
   
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>  

此時(shí)我們發(fā)現(xiàn)最終執(zhí)行的結(jié)果interests為null,這說(shuō)明Mybatis沒(méi)有使用我們定義的StringArrayTypeHandler來(lái)轉(zhuǎn)換interests。

(2)UserMapper.xml還像上面那樣定義,但是也只指定javaType屬性來(lái)注冊(cè)我們的StringArrayTypeHandler,代碼如下:

    <typeHandlers>  
       <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;"/>  
    </typeHandlers>  

這個(gè)時(shí)候再運(yùn)行上面的測(cè)試代碼,輸出結(jié)果發(fā)現(xiàn)interests轉(zhuǎn)換為User類字符串?dāng)?shù)組類型的interests屬性。

這是因?yàn)槲覀兪且詊avaType和null注冊(cè)的StringArrayTypeHandler,然后在需要轉(zhuǎn)換interests時(shí)又是以相同的javaType和null來(lái)尋找的,所以就會(huì)找到我們注冊(cè)的StringArrayTypeHandler來(lái)進(jìn)行類型轉(zhuǎn)換。

3. 只指定變量對(duì)應(yīng)的jdbcType類型

這個(gè)時(shí)候Mybatis會(huì)利用我們指定的返回類型和對(duì)應(yīng)的屬性取該屬性在返回類型中對(duì)應(yīng)的javaType,之后再拿著該javaType和我們指定的jdbcType到注冊(cè)的TypeHandler中獲取對(duì)應(yīng)的TypeHandler。

保持之前指定javaType和jdbcType的方式注冊(cè)StringArrayTypeHandler,然后在定義interests變量的時(shí)候不指定javaType,只指定jdbcType,這個(gè)時(shí)候UserMapper.xml如下所示:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" jdbcType="VARCHAR"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>  

這個(gè)時(shí)候Mybatis是這樣獲取TypeHandler的:首先它發(fā)現(xiàn)我們的interests沒(méi)有指定javaType,這個(gè)時(shí)候它就會(huì)通過(guò)我們指定的類型User和屬性interests獲取User類的interests屬性對(duì)應(yīng)的java類型,即String數(shù)組,再拿著獲取到的javaType和我們指定的jdbcType即VARCHAR去尋找對(duì)應(yīng)的TypeHandler,這個(gè)時(shí)候就找到了我們之前以String數(shù)組和VARCHAR注冊(cè)好的StringArrayTypeHandler來(lái)處理interests的類型轉(zhuǎn)換。

4. javaType類型和jdbcType類型都不指定

這個(gè)時(shí)候Mybatis會(huì)以方式2中的方式獲取到對(duì)應(yīng)的javaType類型,然后再以方式1獲取到對(duì)應(yīng)的TypeHandler。

首先,注冊(cè)一個(gè)javaType為String數(shù)組,jdbcType不指定即為null的TypeHandler—StringArrayTypeHandler,代碼如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration  
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <properties resource="config/jdbc.properties"></properties>  
    <typeAliases>  
       <package name="com.tiantian.mybatis.model"/>  
    </typeAliases>  
    <typeHandlers>  
       <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;"/>  
    </typeHandlers>  
    <environments default="development">  
       <environment id="development">  
           <transactionManager type="JDBC" />  
           <dataSource type="POOLED">  
              <property name="driver" value="${jdbc.driver}" />  
              <property name="url" value="${jdbc.url}" />  
              <property name="username" value="${jdbc.username}" />  
              <property name="password" value="${jdbc.password}" />  
           </dataSource>  
       </environment>  
    </environments>  
    <mappers>  
       <mapper resource="com/tiantian/mybatis/mapper/UserMapper.xml"/>  
    </mappers>  
</configuration>  

然后,定義我們的interests字段的映射關(guān)系時(shí)既不指定javaType,又不指定jdbcType,代碼如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper> 

此時(shí)我們以javaType為String數(shù)組和jdbcType為null注冊(cè)了一個(gè)StringArrayTypeHandler,然后在定義interests字段的映射關(guān)系時(shí)我們沒(méi)有指明其對(duì)應(yīng)的javaType和jdbcType,這個(gè)時(shí)候Mybatis會(huì)利用我們指定的User類型和interests屬性獲取到User類的interests屬性對(duì)應(yīng)的java類型,即String數(shù)組,然后結(jié)合jdbcType為null去尋找注冊(cè)的TypeHandler,這樣就找到了StringArrayTypeHandler。經(jīng)StringArrayTypeHandler的處理就把jdbcType為VARCHAR的數(shù)據(jù)轉(zhuǎn)換為javaType為String數(shù)組的數(shù)據(jù)。
 

5. 直接通過(guò)變量的typeHandler屬性指定其對(duì)應(yīng)的TypeHandler

還有一種形式是我們直接通過(guò)變量的typeHandler屬性指定其對(duì)應(yīng)的TypeHandler,這個(gè)時(shí)候Mybatis就會(huì)使用該用戶自己指定的TypeHandler來(lái)進(jìn)行類型轉(zhuǎn)換,而不再以javaType和jdbcType組合的方式獲取對(duì)應(yīng)的TypeHandler。

首先在Mybatis的配置文件中以javaType和jdbcType配套的方式注冊(cè)一個(gè)StringArrayTypeHandler,代碼如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration  
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <properties resource="config/jdbc.properties"></properties>  
    <typeAliases>  
       <package name="com.tiantian.mybatis.model"/>  
    </typeAliases>  
    <typeHandlers>  
       <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>  
    </typeHandlers>  
    <environments default="development">  
       <environment id="development">  
           <transactionManager type="JDBC" />  
           <dataSource type="POOLED">  
              <property name="driver" value="${jdbc.driver}" />  
              <property name="url" value="${jdbc.url}" />  
              <property name="username" value="${jdbc.username}" />  
              <property name="password" value="${jdbc.password}" />  
           </dataSource>  
       </environment>  
    </environments>  
    <mappers>  
       <mapper resource="com/tiantian/mybatis/mapper/UserMapper.xml"/>  
    </mappers>  
</configuration>  

按照前面說(shuō)的Mybatis按照變量的javaType和jdbcType來(lái)取對(duì)應(yīng)的TypeHandler的話,這里注冊(cè)的StringArrayTypeHandler只有在指定變量的javaType為字符串?dāng)?shù)組而jdbcType為VARCHAR的情況下才能被獲取到。

然后我們?cè)赨serMapper.xml文件中不指定interests字段對(duì)應(yīng)的javaType和jdbcType,但是通過(guò)typeHandler屬性指定將以StringArrayTypeHandler來(lái)進(jìn)行類型轉(zhuǎn)換,代碼如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper  
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" 
typeHandler="com.tiantian.mybatis.handler.StringArrayTypeHandler"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>  

這是因?yàn)槲覀冎付诉M(jìn)行interests字段的映射關(guān)系時(shí)使用StringArrayTypeHandler來(lái)進(jìn)行類型轉(zhuǎn)換。當(dāng)指定了某一個(gè)字段或變量進(jìn)行映射關(guān)系時(shí)所使用的TypeHandler時(shí),Mybatis在需要進(jìn)行類型轉(zhuǎn)換時(shí)就使用給定的TypeHandler進(jìn)行類型轉(zhuǎn)換,而不會(huì)再通過(guò)javaType和jdbcType的組合去注冊(cè)好的TypeHandler中尋找對(duì)應(yīng)的TypeHandler。

相關(guān)文章

  • SpringBoot中的FailureAnalyzer使用詳解

    SpringBoot中的FailureAnalyzer使用詳解

    這篇文章主要介紹了SpringBoot中的FailureAnalyzer使用詳解,Spring Boot的FailureAnalyzer是一個(gè)接口,它用于在Spring Boot應(yīng)用啟動(dòng)失敗時(shí)提供有關(guān)錯(cuò)誤的詳細(xì)信息,這對(duì)于開發(fā)者來(lái)說(shuō)非常有用,因?yàn)樗梢詭椭覀兛焖僮R(shí)別問(wèn)題并找到解決方案,需要的朋友可以參考下
    2023-12-12
  • 解決Error:Java:無(wú)效的源發(fā)行版:14問(wèn)題

    解決Error:Java:無(wú)效的源發(fā)行版:14問(wèn)題

    在項(xiàng)目開發(fā)中,版本不一致常見問(wèn)題,首先,應(yīng)檢查本地JDK版本,使用命令java-version,其次,核對(duì)項(xiàng)目及模塊版本,若有不一致,通過(guò)修改pom.xml文件同步版本,重新下載依賴即可解決問(wèn)題,這種方法簡(jiǎn)單有效,適用于多種開發(fā)環(huán)境
    2024-10-10
  • java基礎(chǔ)實(shí)現(xiàn)猜數(shù)字小游戲

    java基礎(chǔ)實(shí)現(xiàn)猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了java基礎(chǔ)實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • SpringBoot中@ConfigurationProperties實(shí)現(xiàn)配置自動(dòng)綁定的方法

    SpringBoot中@ConfigurationProperties實(shí)現(xiàn)配置自動(dòng)綁定的方法

    本文主要介紹了SpringBoot中@ConfigurationProperties實(shí)現(xiàn)配置自動(dòng)綁定的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java中串行流和并行流區(qū)別小結(jié)

    java中串行流和并行流區(qū)別小結(jié)

    串行流和并行流是兩種處理流操作的方式,串行流適用于小數(shù)據(jù)量且簡(jiǎn)單的數(shù)據(jù)處理,并行流則適用于大規(guī)模數(shù)據(jù)處理和需要并行計(jì)算的場(chǎng)景,能夠利用多線程并行處理,選擇使用哪種流取決于數(shù)據(jù)量大小、處理復(fù)雜度和是否需要并行計(jì)算,下面就來(lái)具體介紹一下兩者的區(qū)別
    2024-09-09
  • Java設(shè)計(jì)模式之代理模式與裝飾模式實(shí)例詳解

    Java設(shè)計(jì)模式之代理模式與裝飾模式實(shí)例詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式之代理模式與裝飾模式,結(jié)合具體實(shí)例形式分析了代理模式與裝飾模式的概念、功能、java實(shí)現(xiàn)方法與相關(guān)使用注意事項(xiàng),需要的朋友可以參考下
    2017-09-09
  • 使用quartz時(shí),傳入?yún)?shù)到j(luò)ob中的使用記錄

    使用quartz時(shí),傳入?yún)?shù)到j(luò)ob中的使用記錄

    這篇文章主要介紹了使用quartz時(shí),傳入?yún)?shù)到j(luò)ob中的使用記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 使用Spring boot 的profile功能實(shí)現(xiàn)多環(huán)境配置自動(dòng)切換

    使用Spring boot 的profile功能實(shí)現(xiàn)多環(huán)境配置自動(dòng)切換

    這篇文章主要介紹了使用Spring boot 的profile功能實(shí)現(xiàn)多環(huán)境配置自動(dòng)切換的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-11-11
  • SpringMVC攔截器詳解

    SpringMVC攔截器詳解

    本篇文章主要介紹了SpringMVC攔截器配置及使用方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-07-07
  • 在IDEA中搭建最小可用SpringMVC項(xiàng)目(純Java配置)

    在IDEA中搭建最小可用SpringMVC項(xiàng)目(純Java配置)

    這篇文章主要介紹了在IDEA中搭建最小可用SpringMVC項(xiàng)目(純Java配置),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論