微服務(wù)mybatis?typehandler使用詳解(就這一篇夠了)
Mybatis TypeHandler類型轉(zhuǎn)換器是負(fù)責(zé)Java類和jdbc
類型之間的轉(zhuǎn)換
主要涉及到下面這幾個類:
TypeHandler
類型轉(zhuǎn)換器的頂層接口BaseTypeHandler
抽象類繼承自TypeHandler
,Mybatis
中所有的類型轉(zhuǎn)換器實現(xiàn)均繼承他。TypeHandlerRegistry
類型轉(zhuǎn)換器注冊器,負(fù)責(zé)存儲類型轉(zhuǎn)換器。TypeAliasRegistry
類型別名轉(zhuǎn)換器,用來存儲類型與別名的對應(yīng)關(guān)系。
1 TypeHandler
TypeHandler
是類型轉(zhuǎn)換器的頂層接口,其定義了類型轉(zhuǎn)換器應(yīng)該具有的功能,
TypeHandler主要解決了兩個問題:
- 可以指定我們在Java實體類所包含的自定義類型存入數(shù)據(jù)庫后的類型是什么
- 從數(shù)據(jù)庫中取出該數(shù)據(jù)后自動轉(zhuǎn)換為我們自定義的Java類型
其源碼如下:
public interface TypeHandler<T> { /** * 用于定義在Mybatis設(shè)置參數(shù)時該如何把Java類型的參數(shù)轉(zhuǎn)換為對應(yīng)的數(shù)據(jù)庫類型 * @param ps 當(dāng)前的PreparedStatement對象 * @param i 當(dāng)前參數(shù)的位置 * @param parameter 當(dāng)前參數(shù)的Java對象 * @param jdbcType 當(dāng)前參數(shù)的數(shù)據(jù)庫類型 * @throws SQLException */ void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; /** * 用于在Mybatis獲取數(shù)據(jù)結(jié)果集時如何把數(shù)據(jù)庫類型轉(zhuǎn)換為對應(yīng)的Java類型 * @param rs 當(dāng)前的結(jié)果集 * @param columnName 當(dāng)前的字段名稱 * @return 轉(zhuǎn)換后的Java對象 * @throws SQLException */ T getResult(ResultSet rs, String columnName) throws SQLException; /** * 用于在Mybatis通過字段位置獲取字段數(shù)據(jù)時把數(shù)據(jù)庫類型轉(zhuǎn)換為對應(yīng)的Java類型 * @param rs 當(dāng)前的結(jié)果集 * @param columnIndex 當(dāng)前字段的位置 * @return 轉(zhuǎn)換后的Java對象 * @throws SQLException */ T getResult(ResultSet rs, int columnIndex) throws SQLException; /** * 用于Mybatis在調(diào)用存儲過程后把數(shù)據(jù)庫類型的數(shù)據(jù)轉(zhuǎn)換為對應(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
是一個抽象類,改類實現(xiàn)了TypeHandler
中的方法并實現(xiàn)了異常捕獲。繼承改類我們可以很容易的實現(xiàn)一個自定義類型轉(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對TypeHandler接口的四個方法做了一個簡單的選擇,把null值的情況都做了一個過濾,核心的取值和設(shè)值的方法還是抽象出來了供子類來實現(xiàn)。使用BaseTypeHandler還有一個好處是它繼承了另外一個叫做TypeReference的抽象類,通過TypeReference的getRawType()方法可以獲取到當(dāng)前TypeHandler所使用泛型的原始類型。這對Mybatis在注冊TypeHandler的時候是非常有好處的。在沒有指定javaType的情況下,Mybatis在注冊TypeHandler時可以通過它來獲取當(dāng)前TypeHandler所使用泛型的原始類型作為要注冊的TypeHandler的javaType類型,這個在講到Mybatis注冊TypeHandler的方式時將講到。
3 注冊TypeHandler
為什么Java自帶的類型在存取的時候不會出錯,我們自定義的類型就會出錯?那是因為mybatis已經(jīng)將這些類型的TypeHandler提前寫好了,并且注冊好了
具體注冊了哪些,我們可以看TypeHandlerRegistry這個類:
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. 實現(xiàn)自定義的TypeHandler
我們可以直接繼承BaseTypeHandler來實現(xiàn)我們自己的類型轉(zhuǎn)換器
我們要實現(xiàn)把json字符串轉(zhuǎn)換成為我們的對象,可以這么實現(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對象轉(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對象失敗", e); } } }
因為我們使用的是Spring 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自動獲取TypeHandle
在介紹了Mybatis是如何注冊TypeHandler之后就介紹一下Mybatis是如何獲取對應(yīng)的TypeHandler進(jìn)行類型轉(zhuǎn)換的。
如果我們在Mapper.xml文件中配置某一個屬性或變量的映射關(guān)系時指定了該屬性對應(yīng)的javaType和jdbcType,則Mybatis會從注冊好的TypeHandler中尋找對應(yīng)的javaType和jdbcType組合的TypeHandler進(jìn)行處理,這也是Mybatis最基本的獲取TypeHandler進(jìn)行類型轉(zhuǎn)換的方式。
1.javaType和jdbcType都指定
假設(shè)Mybatis配置文件中有這么一段TypeHandler的注冊信息:
<typeHandlers> <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/> </typeHandlers>
看這樣一個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中,我們定義了一個對應(yīng)字段interests的映射關(guān)系,并且定義了其javaType為“[Ljava.lang.String;”,jdbcType為VARCHAR,這個時候Mybatis就會到已經(jīng)注冊了的TypeHandler中尋找到能處理javaType和jdbcType對應(yīng)的類型轉(zhuǎn)換的TypeHandler來進(jìn)行處理。在這里就會找到我們注冊的StringArrayTypeHandler。在上面id為insertUser的insert語句中,我們也為變量interests指定了它的javaType和jdbcType屬性,這時候Mybatis也會尋找javaType和jdbcType對應(yīng)的TypeHandler。上面這樣定義是Mybatis最基本也是最完整地獲取到對應(yīng)的TypeHandler的方法。
2. 只指定變量對應(yīng)的javaType類型。
這個時候Mybatis會拿著這個javaType和jdbcType為null的組合到注冊的TypeHandler中尋找對應(yīng)的TypeHandler。
(1)不動StringArrayTypeHandler的注冊信息,把我們的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>
此時我們發(fā)現(xiàn)最終執(zhí)行的結(jié)果interests為null,這說明Mybatis沒有使用我們定義的StringArrayTypeHandler來轉(zhuǎn)換interests。
(2)UserMapper.xml還像上面那樣定義,但是也只指定javaType屬性來注冊我們的StringArrayTypeHandler,代碼如下:
<typeHandlers> <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;"/> </typeHandlers>
這個時候再運行上面的測試代碼,輸出結(jié)果發(fā)現(xiàn)interests轉(zhuǎn)換為User類字符串?dāng)?shù)組類型的interests屬性。
這是因為我們是以javaType和null注冊的StringArrayTypeHandler,然后在需要轉(zhuǎn)換interests時又是以相同的javaType和null來尋找的,所以就會找到我們注冊的StringArrayTypeHandler來進(jìn)行類型轉(zhuǎn)換。
3. 只指定變量對應(yīng)的jdbcType類型
這個時候Mybatis會利用我們指定的返回類型和對應(yīng)的屬性取該屬性在返回類型中對應(yīng)的javaType,之后再拿著該javaType和我們指定的jdbcType到注冊的TypeHandler中獲取對應(yīng)的TypeHandler。
保持之前指定javaType和jdbcType的方式注冊StringArrayTypeHandler,然后在定義interests變量的時候不指定javaType,只指定jdbcType,這個時候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>
這個時候Mybatis是這樣獲取TypeHandler的:首先它發(fā)現(xiàn)我們的interests沒有指定javaType,這個時候它就會通過我們指定的類型User和屬性interests獲取User類的interests屬性對應(yīng)的java類型,即String數(shù)組,再拿著獲取到的javaType和我們指定的jdbcType即VARCHAR去尋找對應(yīng)的TypeHandler,這個時候就找到了我們之前以String數(shù)組和VARCHAR注冊好的StringArrayTypeHandler來處理interests的類型轉(zhuǎn)換。
4. javaType類型和jdbcType類型都不指定
這個時候Mybatis會以方式2中的方式獲取到對應(yīng)的javaType類型,然后再以方式1獲取到對應(yīng)的TypeHandler。
首先,注冊一個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)系時既不指定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>
此時我們以javaType為String數(shù)組和jdbcType為null注冊了一個StringArrayTypeHandler,然后在定義interests字段的映射關(guān)系時我們沒有指明其對應(yīng)的javaType和jdbcType,這個時候Mybatis會利用我們指定的User類型和interests屬性獲取到User類的interests屬性對應(yīng)的java類型,即String數(shù)組,然后結(jié)合jdbcType為null去尋找注冊的TypeHandler,這樣就找到了StringArrayTypeHandler。經(jīng)StringArrayTypeHandler的處理就把jdbcType為VARCHAR的數(shù)據(jù)轉(zhuǎn)換為javaType為String數(shù)組的數(shù)據(jù)。
5. 直接通過變量的typeHandler屬性指定其對應(yīng)的TypeHandler
還有一種形式是我們直接通過變量的typeHandler屬性指定其對應(yīng)的TypeHandler,這個時候Mybatis就會使用該用戶自己指定的TypeHandler來進(jìn)行類型轉(zhuǎn)換,而不再以javaType和jdbcType組合的方式獲取對應(yīng)的TypeHandler。
首先在Mybatis的配置文件中以javaType和jdbcType配套的方式注冊一個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>
按照前面說的Mybatis按照變量的javaType和jdbcType來取對應(yīng)的TypeHandler的話,這里注冊的StringArrayTypeHandler只有在指定變量的javaType為字符串?dāng)?shù)組而jdbcType為VARCHAR的情況下才能被獲取到。
然后我們在UserMapper.xml文件中不指定interests字段對應(yīng)的javaType和jdbcType,但是通過typeHandler屬性指定將以StringArrayTypeHandler來進(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>
這是因為我們指定了進(jìn)行interests字段的映射關(guān)系時使用StringArrayTypeHandler來進(jìn)行類型轉(zhuǎn)換。當(dāng)指定了某一個字段或變量進(jìn)行映射關(guān)系時所使用的TypeHandler時,Mybatis在需要進(jìn)行類型轉(zhuǎn)換時就使用給定的TypeHandler進(jìn)行類型轉(zhuǎn)換,而不會再通過javaType和jdbcType的組合去注冊好的TypeHandler中尋找對應(yīng)的TypeHandler。
- mybatis之BaseTypeHandler用法解讀
- mybatis-plus之自動映射字段(typeHandler)的注意點及說明
- MyBatisPlus?TypeHandler自定義字段類型轉(zhuǎn)換Handler
- mybatis TypeHandler注入spring的依賴方式
- MybatisPlus如何自定義TypeHandler映射JSON類型為List
- Mybatis自定義TypeHandler解決特殊類型轉(zhuǎn)換問題詳解
- MyBatis自定義typeHandler的完整實例
- Mybatis實現(xiàn)自定義類型轉(zhuǎn)換器TypeHandler的方法
- Mybatis實現(xiàn)自定義的typehandler三步曲
相關(guān)文章
SpringBoot中的FailureAnalyzer使用詳解
這篇文章主要介紹了SpringBoot中的FailureAnalyzer使用詳解,Spring Boot的FailureAnalyzer是一個接口,它用于在Spring Boot應(yīng)用啟動失敗時提供有關(guān)錯誤的詳細(xì)信息,這對于開發(fā)者來說非常有用,因為它可以幫助我們快速識別問題并找到解決方案,需要的朋友可以參考下2023-12-12java基礎(chǔ)實現(xiàn)猜數(shù)字小游戲
這篇文章主要為大家詳細(xì)介紹了java基礎(chǔ)實現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11SpringBoot中@ConfigurationProperties實現(xiàn)配置自動綁定的方法
本文主要介紹了SpringBoot中@ConfigurationProperties實現(xiàn)配置自動綁定的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02使用quartz時,傳入?yún)?shù)到j(luò)ob中的使用記錄
這篇文章主要介紹了使用quartz時,傳入?yún)?shù)到j(luò)ob中的使用記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12使用Spring boot 的profile功能實現(xiàn)多環(huán)境配置自動切換
這篇文章主要介紹了使用Spring boot 的profile功能實現(xiàn)多環(huán)境配置自動切換的相關(guān)知識,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下2018-11-11在IDEA中搭建最小可用SpringMVC項目(純Java配置)
這篇文章主要介紹了在IDEA中搭建最小可用SpringMVC項目(純Java配置),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12