【问题标题】:Kotlin, Spring Boot, JPA - take value of a Generic Enum (E.valueOf(stringValue))Kotlin,Spring Boot,JPA - 获取通用枚举的值 (E.valueOf(stringValue))
【发布时间】:2021-07-27 16:59:28
【问题描述】:

背景

我正在开发一个 Spring Boot 应用程序,我正在使用 Kotlin、IntelliJ 和 Gradle (Groovy)。我的代码中有一些enum class,我需要保留它们(使用JPA)。我使用了一个简单的全局转换器。

// Sample Enum
enum class Policy {
    PUBLIC,
    INVITE_ONLY
}

// Sample Converter
@Converter(autoApply = true)
class PolicyConverter : AttributeConverter<Policy, String> {
    override fun convertToDatabaseColumn(attribute: Policy): String {
        return attribute.name
    }
    override fun convertToEntityAttribute(dbData: String): Policy {
        return Policy.valueOf(dbData.toUpperCase())
    }
}

问题

因为我有 5-6 个枚举并且我讨厌重复的代码,所以我想到了一个通用转换器,它应该为每个给定的枚举完成工作。我试图编写一些代码,但没有任何效果。这就是我的想法:

abstract class EnumConverter<E: Enum<E>> : AttributeConverter<E, String> {
    override fun convertToDatabaseColumn(attribute: E): String {
        return attribute.name
    }

    override fun convertToEntityAttribute(dbData: String): E {
        return E.valueOf(dbData.toUpperCase())
    }
}

这样我只能从一个抽象类扩展每个枚举转换器,如下所示:

@Converter(autoApply = true)
class PolicyConverter : EnumConverter<Policy>() {}

这段代码的问题是我有两个错误:

  • E 是红色的,因为:类型参数 'E' 不能拥有或继承伴随对象,因此它不能位于点的左侧
  • valueOf 是红色的,因为:未解析的引用(.valueOf 有 150 多种类型)。

根据this 的建议,我尝试使用以下功能:

private inline fun <reified E : Enum<E>> getValue(string: String): E {
    return enumValueOf(string.toUpperCase())
}

但是当从.convertToEntityAttribute调用时,结果是“不能使用'E'作为具体类型参数。使用类代替。

问题

所以问题很简单:我怎样才能实现一种简单快捷的方法来为我的所有枚举制作一个转换器,所有这些都遵循相同的原则?我只需要一个return E.valueOf(&lt;value&gt;) 函数,但它不存在。

【问题讨论】:

    标签: spring-boot kotlin jpa generics enums


    【解决方案1】:

    这个问题的一个简单的解决方法是定义一个抽象方法,每个类都将实现它,它会返回正确的类型,给定一个字符串。

    // Inside EnumConverter, the Generic Class
    abstract class EnumConverter<E: Enum<E>> : AttributeConverter<E, String> {
        abstract fun getValueFromString(string: String) : E
    
        override fun convertToEntityAttribute(dbData: String): E {
            return getValueFromString(dbData)
        }
        [...]
    }
    
    // Inside Policy Enum, implementing
    class PolicyConverter : EnumConverter<Policy>() {
        override fun getValueFromString(string: String): Policy {
            return Policy.valueOf(string.toUpperCase())
        }
    }
    

    但这是我非常不喜欢的解决方法。

    【讨论】:

      猜你喜欢
      • 2020-04-15
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      相关资源
      最近更新 更多