You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免为枚举转Short/Int编写多个AttributeConverter?

通用枚举转Short的AttributeConverter实现方案

问题背景

目前通过编写AttributeConverter实现枚举与Short类型的数据库持久化转换,但已有约10个重复的转换器实现,代码冗余严重。同时因枚举顺序变更会引发数据异常,不考虑使用@Enumerated(EnumType.ORDINAL)方案。

通用解决方案

1. 定义枚举通用接口

创建一个统一接口,让所有需要转换的枚举类实现它,规范值的获取与转换逻辑:

interface ShortValuedEnum {
    val value: Short

    companion object {
        inline fun <reified T : ShortValuedEnum> fromValue(value: Short): T {
            return enumValues<T>().firstOrNull { it.value == value }
                ?: throw IllegalArgumentException("Invalid value: $value for enum ${T::class.simpleName}")
        }
    }
}

2. 实现通用转换器

编写泛型版AttributeConverter,基于上述接口实现通用的双向转换逻辑:

@Converter(autoApply = true)
class ShortEnumConverter<E : Enum<E> & ShortValuedEnum> : AttributeConverter<E, Short> {

    override fun convertToDatabaseColumn(attribute: E?): Short? {
        return attribute?.value
    }

    override fun convertToEntityAttribute(dbData: Short?): E? {
        return dbData?.let { ShortValuedEnum.fromValue(it) }
    }
}

注:设置autoApply = true后,所有实现ShortValuedEnum的枚举会自动应用该转换器,无需在实体类中单独声明@Convert;若需个别例外,可单独指定转换器覆盖全局配置。

3. 修改现有枚举类

让你的枚举实现ShortValuedEnum接口,移除原重复的转换方法:

enum class MyEnum(override val value: Short) : ShortValuedEnum {
    RED(0),
    GREEN(1);
}

4. 实体类使用示例

现在实体类无需指定特定转换器,直接声明枚举类型即可:

@Entity
@Table(name = "my_table")
class MyEntity(
    @Id
    val id: Long,

    @Column(name = "status", nullable = false)
    val color: MyEnum
)

若不需要全局自动应用,也可手动指定通用转换器:

@Convert(converter = ShortEnumConverter::class)
@Column(name = "status", nullable = false)
val color: MyEnum

方案优势

  • 彻底消除重复的转换器代码,所有符合规范的枚举可复用同一转换器
  • 规避EnumType.ORDINAL的顺序依赖风险,基于枚举固定value字段转换
  • 支持全局自动应用或手动指定两种模式,适配不同业务场景

内容的提问来源于stack exchange,提问作者KotlinOverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:52:21