MyBatis 默认不支持枚举与数据库字段自动转换,需通过 TypeHandler 显式映射;推荐定义含 code 和 desc 字段的枚举类,并配合自定义 OrderStatusTypeHandler 实现 code 与 INT 字段双向转换,或全局配置 EnumTypeHandler 映射 name 到 VARCHAR。

Java 枚举类在 MyBatis 中默认无法自动与数据库字段(如 INT 或 VARCHAR)互相转换,需通过 EnumTypeHandler 显式配置映射规则。核心是让 MyBatis 知道:枚举的哪个字段(如 code 或 name)对应数据库中的值。
定义带属性的枚举类
推荐枚举实现业务语义明确的字段,例如用 code 存数据库值,desc 作描述:
public enum OrderStatus {
INIT(0, "初始化"),
PAID(1, "已支付"),
SHIPPED(2, "已发货"),
COMPLETED(3, "已完成");
<pre class="brush:php;toolbar:false;">private final int code;
private final String desc;
OrderStatus(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() { return code; }
public String getDesc() { return desc; }
// 提供根据 code 反查枚举的静态方法(MyBatis 反向映射必需)
public static OrderStatus fromCode(int code) {
for (OrderStatus status : OrderStatus.values()) {
if (status.code == code) {
return status;
}
}
throw new IllegalArgumentException("Unknown code: " + code);
}}
注册 EnumTypeHandler(两种方式)
MyBatis 提供了内置的 EnumOrdinalTypeHandler(按序号)和 EnumTypeHandler(按 name),但更常用的是自定义 handler 或直接使用 EnumTypeHandler 配合枚举的 getter 方法。
-
方式一:全局配置(推荐) —— 在
mybatis-config.xml中注册为默认枚举处理器:
<configuration><typehandlers><typehandler handler="org.apache.ibatis.type.EnumTypeHandler" javatype="com.example.OrderStatus"></typehandler></typehandlers></configuration>
此时 MyBatis 默认使用枚举的 name()(即 INIT、PAID)与数据库 VARCHAR 字段映射。若数据库存的是数字(如 0、1),则不适用。
-
方式二:指定字段映射(最常用) —— 使用
EnumOrdinalTypeHandler(存序号)或自定义 handler(存自定义字段):
若数据库字段是 TINYINT 存 code 值,建议写一个轻量自定义 handler:
public class OrderStatusTypeHandler extends BaseTypeHandler<orderstatus> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, OrderStatus parameter, JdbcType jdbcType)
throws SQLException {
ps.setInt(i, parameter.getCode());
}
<pre class="brush:php;toolbar:false;">@Override
public OrderStatus getNullableResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
return rs.wasNull() ? null : OrderStatus.fromCode(code);
}
// 其余两个 getNullableResult 重载方法类似,可调用上面逻辑
}
然后在 XML 映射文件中显式指定:
<resultmap id="OrderResultMap" type="Order"><id property="id" column="id"></id><result property="status" column="status_code" typehandler="com.example.OrderStatusTypeHandler"></result></resultmap>
注解方式(Mapper 接口 + @Select/@Insert)
使用 @Select 等注解时,可在参数或结果上直接指定 handler:
@Select("SELECT * FROM orders WHERE status_code = #{status.code}")
List<order> selectByStatus(@Param("status") OrderStatus status);
<p>@Results({
@Result(property = "status", column = "status_code",
typeHandler = OrderStatusTypeHandler.class)
})
@Select("SELECT * FROM orders")
List<order> findAll();
</order></p></order>
注意事项
- 数据库字段类型要与 handler 写入/读取的类型一致(如 handler 写
int,字段就得是INT/TINYINT) - 必须提供从数据库值反查枚举实例的静态方法(如
fromCode),否则反序列化会失败 - 若枚举字段名不是
code,而是value或id,handler 中相应调整 getter 调用即可 - Spring Boot 项目可在
application.yml中配置全局 type-handlers:
mybatis:
configuration:
type-handlers-package: com.example.handler
这样包下所有继承 BaseTypeHandler 的类会被自动注册。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











