在 MyBatis 中,TypeHandler
是一个非常关键的接口,它的作用是在 Java 类型和 JDBC 类型之间进行转换,用来处理 Java 对象与数据库字段之间的映射关系,特别是在类型不一致或需要特殊转换逻辑时。
一、TypeHandler 的作用:
MyBatis 默认已经提供了一些常见类型的 TypeHandler
,比如 StringTypeHandler
、IntegerTypeHandler
等。但在以下场景下我们通常需要自定义:
- Java 与数据库字段类型不一致,比如数据库是
VARCHAR
,Java 中是enum
; - 需要将一个对象序列化成 JSON 存入数据库,或反过来;
- 存取布尔值、日期等,需要特定格式处理。
二、TypeHandler 接口方法说明:
接口:org.apache.ibatis.type.TypeHandler<T>
常用方法包括:
// 设置参数
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType);
// 获取结果(通过列名)
T getResult(ResultSet rs, String columnName);
// 获取结果(通过列索引)
T getResult(ResultSet rs, int columnIndex);
// 获取结果(用于存储过程)
T getResult(CallableStatement cs, int columnIndex);
三、如何自定义 TypeHandler
示例:将 Enum 类型映射为数据库中的整数
假设我们有一个性别枚举:
public enum Gender {
MALE(1),
FEMALE(2);
private final int code;
Gender(int code) { this.code = code; }
public int getCode() { return code; }
public static Gender fromCode(int code) {
for (Gender g : values()) {
if (g.code == code) return g;
}
throw new IllegalArgumentException("Invalid code: " + code);
}
}
自定义 TypeHandler:
@MappedTypes(Gender.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class GenderTypeHandler implements TypeHandler<Gender> {
@Override
public void setParameter(PreparedStatement ps, int i, Gender gender, JdbcType jdbcType) throws SQLException {
ps.setInt(i, gender.getCode());
}
@Override
public Gender getResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
return Gender.fromCode(code);
}
@Override
public Gender getResult(ResultSet rs, int columnIndex) throws SQLException {
int code = rs.getInt(columnIndex);
return Gender.fromCode(code);
}
@Override
public Gender getResult(CallableStatement cs, int columnIndex) throws SQLException {
int code = cs.getInt(columnIndex);
return Gender.fromCode(code);
}
}
四、注册方式
- 在 MyBatis 配置文件中手动注册:
<typeHandlers>
<typeHandler handler="com.example.handler.GenderTypeHandler"/>
</typeHandlers>
- 或使用注解自动扫描(推荐):
在 MyBatis 配置中配置包扫描:
<typeHandlers>
<package name="com.example.handler"/>
</typeHandlers>
- 或在 Mapper 参数上使用注解:
@Select("SELECT * FROM user WHERE id = #{id}")
@Results({
@Result(property = "gender", column = "gender", typeHandler = GenderTypeHandler.class)
})
User getUserById(@Param("id") int id);
五、常见用法扩展:
- Java Enum ↔ INT、String
- JSON 字符串 ↔ Java 对象(可结合 Jackson)
- 日期时间格式定制化处理
- 布尔值 ↔ “Y”/”N”