1. 深入理解MyBatis类型处理机制
在数据库操作中,Java对象与数据库字段之间的类型转换是一个常见需求。MyBatis通过TypeHandler机制优雅地解决了这个问题。理解这个机制的工作原理,是掌握自定义类型处理的基础。
TypeHandler本质上是一个双向转换器,负责处理两种场景:
- 当Java对象需要存入数据库时,将Java类型转换为JDBC类型
- 当从数据库读取数据时,将JDBC类型转换回Java类型
MyBatis内置了数十种常见类型的处理器,比如:
- StringTypeHandler:处理String与VARCHAR的转换
- IntegerTypeHandler:处理Integer与INTEGER的转换
- DateTypeHandler:处理Date与TIMESTAMP的转换
但当我们遇到特殊类型时,比如枚举、JSON对象、自定义数据结构等,就需要自己实现TypeHandler。这就像是在Java类型系统和数据库类型系统之间架设一座桥梁。
提示:在实现自定义TypeHandler前,建议先检查MyBatis是否已经提供了对应的处理器。例如枚举类型,MyBatis提供了EnumTypeHandler和EnumOrdinalTypeHandler两种实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 定义自定义类型与处理器
2.1 设计状态枚举类型
让我们以一个典型的状态枚举为例。在业务系统中,状态字段通常会用数字代码存储在数据库中,但在Java代码中我们更希望使用枚举类型,这样代码更清晰、更类型安全。
java复制public enum StatusEnum {
ACTIVE(1, "活跃"),
INACTIVE(0, "不活跃"),
LOCKED(2, "锁定"),
DELETED(-1, "已删除");
private final int code;
private final String description;
StatusEnum(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
public static StatusEnum fromCode(int code) {
for (StatusEnum status : StatusEnum.values()) {
if (status.getCode() == code) {
return status;
}
}
throw new IllegalArgumentException("无效的状态码: " + code);
}
}
这个枚举设计有几个关键点:
- 每个枚举值对应一个数字code,这是存储在数据库中的实际值
- 提供了fromCode方法,用于从数据库值重建枚举实例
- 包含了description字段,方便展示给用户看
2.2 实现自定义TypeHandler
现在我们需要实现一个TypeHandler,在StatusEnum和数据库INTEGER类型之间进行转换:
java复制import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.*;
public class StatusTypeHandler extends BaseTypeHandler<StatusEnum> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
StatusEnum parameter, JdbcType jdbcType) throws SQLException {
// Java对象 → 数据库:将枚举的code存入数据库
ps.setInt(i, parameter.getCode());
}
@Override
public StatusEnum getNullableResult(ResultSet rs, String columnName)
throws SQLException {
// 数据库 → Java对象:通过列名获取
int code = rs.getInt(columnName);
retur
