全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-20 6 分钟 ✍️ juanwangdev

枚举类型处理

Java 枚举与数据库字段的映射是日常开发中的高频场景。MyBatis 提供了两种内置枚举处理器,同时支持自定义 TypeHandler 实现更灵活的映射策略。

内置枚举处理器

EnumTypeHandler(默认)

MyBatis 默认使用 EnumTypeHandler,它使用枚举的 name() 方法获取枚举名称进行映射:

Java
public enum OrderStatus {
    PENDING,    // name = "PENDING"
    PAID,       // name = "PAID"
    SHIPPED,    // name = "SHIPPED"
    COMPLETED   // name = "COMPLETED"
}

数据库存储的是字符串:

idstatus
1PENDING
2PAID
3SHIPPED

无需额外配置即可使用,因为它是默认策略:

XML
<!-- 无需配置,MyBatis 自动处理 -->
<resultMap id="orderResultMap" type="Order">
    <result column="status" property="status"/>
</resultMap>

EnumOrdinalTypeHandler

使用枚举的 ordinal() 方法(从 0 开始的索引值)进行映射:

Java
public enum OrderStatus {
    PENDING,    // ordinal = 0
    PAID,       // ordinal = 1
    SHIPPED,    // ordinal = 2
    COMPLETED   // ordinal = 3
}

数据库存储的是整数:

idstatus
10
21
32

需要显式注册:

XML
<!-- 方式一:mybatis-config.xml 全局注册 -->
<typeHandlers>
    <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
                 javaType="com.example.OrderStatus"/>
</typeHandlers>

或在 Mapper XML 中为特定字段指定:

XML
<!-- 方式二:字段级别指定 -->
<resultMap id="orderResultMap" type="Order">
    <result column="status" property="status"
            typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</resultMap>

两种内置处理器对比

特性EnumTypeHandlerEnumOrdinalTypeHandler
默认启用否,需手动注册
存储值枚举名称(字符串)枚举索引(整数)
数据库字段类型VARCHAR/CHARINT/TINYINT
可读性好,直接看名称差,需要查枚举定义
枚举顺序变更影响无影响有影响,索引值会变
存储空间较大(字符串)较小(整数)

警告:使用 EnumOrdinalTypeHandler 时,如果修改了枚举项的顺序或增删了枚举项,会导致已有数据索引错乱。生产环境推荐优先使用 EnumTypeHandler 或自定义 TypeHandler。

自定义枚举 TypeHandler(code 值映射)

当数据库使用自定义 code 值(既不是 name 也不是 ordinal)时,需要自定义 TypeHandler:

Java
public enum OrderStatus {
    PENDING("0", "待处理"),
    PAID("1", "已支付"),
    SHIPPED("2", "已发货"),
    COMPLETED("3", "已完成");

    private final String code;
    private final String label;

    OrderStatus(String code, String label) {
        this.code = code;
        this.label = label;
    }

    public String getCode() { return code; }
    public String getLabel() { return label; }

    // 根据 code 反查枚举
    public static OrderStatus fromCode(String code) {
        for (OrderStatus status : values()) {
            if (status.code.equals(code)) {
                return status;
            }
        }
        return null;
    }
}

编写 TypeHandler:

Java
@MappedTypes({OrderStatus.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class OrderStatusTypeHandler extends BaseTypeHandler<OrderStatus> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i,
            OrderStatus status, JdbcType jdbcType) throws SQLException {
        ps.setString(i, status.getCode());
    }

    @Override
    public OrderStatus getNullableResult(ResultSet rs,
            String columnName) throws SQLException {
        return OrderStatus.fromCode(rs.getString(columnName));
    }

    @Override
    public OrderStatus getNullableResult(ResultSet rs,
            int columnIndex) throws SQLException {
        return OrderStatus.fromCode(rs.getString(columnIndex));
    }

    @Override
    public OrderStatus getNullableResult(CallableStatement cs,
            int columnIndex) throws SQLException {
        return OrderStatus.fromCode(cs.getString(columnIndex));
    }
}

数据库存储自定义 code:

idstatus
10
21
32

注册自定义枚举 TypeHandler

方式一:mybatis-config.xml

XML
<typeHandlers>
    <typeHandler handler="com.example.handler.OrderStatusTypeHandler"/>
</typeHandlers>

方式二:包扫描(推荐)

XML
<typeHandlers>
    <package name="com.example.handler"/>
</typeHandlers>

配合注解使用,无需 XML 配置:

Java
@MappedTypes({OrderStatus.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class OrderStatusTypeHandler extends BaseTypeHandler<OrderStatus> {
    // ...
}

方式三:Mapper XML 字段级指定

XML
<resultMap id="orderResultMap" type="Order">
    <result column="status" property="status"
            typeHandler="com.example.handler.OrderStatusTypeHandler"/>
</resultMap>

要点总结

  • EnumTypeHandler 是默认策略,使用枚举名称(字符串)进行映射
  • EnumOrdinalTypeHandler 使用枚举索引(整数)进行映射,需要显式注册
  • 枚举顺序变更时,EnumOrdinalTypeHandler 会导致数据索引错乱,生产环境慎用
  • 数据库使用自定义 code 值时,需编写自定义 TypeHandler 实现 setNonNullParameter(写)和 getNullableResult(读)
  • 自定义枚举 TypeHandler 推荐继承 BaseTypeHandler 减少样板代码
  • 注册方式支持 XML 配置、注解 @MappedTypes、包扫描和 XML 字段级指定四种
  • 字段级 typeHandler 配置优先级高于全局注册

📝 发现内容有误?点击此处直接编辑

← 上一篇 枚举字段映射
下一篇 → ExecutorType 批量执行
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库