java 如何避免AttributeConvertor将Enums转换为short/Int?[副本]

gopyfrb3  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(207)

此问题已在此处有答案

Generic enum JPA AttributeConverter implementation(3个答案)
2天前关闭。
我使用AttributeConvertor将枚举转换为Short,同时将值保存在数据库中,反之亦然,同时从数据库阅读值,如下所示:

@Converter
class MyEnumConvertor : AttributeConverter<MyEnum, Short> {

    override fun convertToDatabaseColumn(attribute: MyEnum): Short = MyEnum.toValue(attribute)

    override fun convertToEntityAttribute(dbData: Short): MyEnum = MyEnum.fromValue(dbData)
}

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

    companion object {
        private val valueToEnumMap = MyEnum.values().associateBy(MyEnum::value)
        fun fromValue(value: Short): MyEnum = valueToEnumMap[value]
            ?: throw Exception("Invalid value: $value")

        fun toValue(status: MyEnum): Short = status.value
    }
}

使用方法:

@Entity
@Table(name = "my_table")
class MyEntity(

    @Id
    val id: Long,

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

现在在其他表中,我也有很多这样的转换,现在大约有10个转换器。我认为拥有这么多转换器不是一个好的做法。
************或者,任何genric解决方案,我可以创建一个转换器,并重用它们?

PS:我知道@Enumerated(Enumtype.ORDINAL)可以工作,但是如果枚举的顺序被改变了(比如,红色和绿色的顺序),那么它就会破坏代码。所以,不要使用这种方法。

w1e3prcc

w1e3prcc1#

我认为你应该能够通过以下方式广泛地做到这一点:
1.定义一个接口,如下所示:interface WithValue { val value: Short }
1.要求每个value枚举都实现此接口

  • 创建一个使用Enum的转换器
  • 在序列化过程中,查看Enum是否实现了WithValue,如果实现了特殊序列化,则调用Enum的标准处理
  • 在反序列化过程中,查看传入节点是否具有符合Short的值(可能是Number),如果是,请使用特殊版本,否则调用Enums的标准处理
  • Module中注册一次转换器,并将您的ObjectMapper声明为Spring bean,以便Spring在任何地方使用它:
@Bean
    fun makeObjectMapper(): ObjectMapper {
        return JsonMapper.builder()
            .addModule(KotlinModule.Builder().configure(KotlinFeature.StrictNullChecks, true).build())
            .addModule(MySpecialValueBasedEnumModule())
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .build()
    }

(我不得不问为什么要麻烦?难道枚举名称不够好--对人类来说足够清楚,对机器索引来说足够高效吗?)

相关问题