繁体   English   中英

如何在数据库中存储Enum类名和枚举值

[英]How to store Enum class name and enum value in database

我有一个带有不同枚举的类,例如:

class EligibilityRule{
ProductEligibility productEligibility;
CountryEligibility countryEligibility
}

enum ProductEligibility{
PRODUCT_X,
PRODUCT_Y
}

enum CountryEligibility{
US,
IN,
CN
..
}

我想将这些不同的枚举类名称及其值存储到称为eligibility rule数据库表中,并且我的表架构看起来像这样,

String id  => auto_increment id
String ruleType => enum class name (ex: ProductEligibility)
String ruleValue => enum value (ex: PRODUCT_X)

我使用的是JOOQ,过去我曾经使用强制类型来存储枚举值。 但是,在这种情况下,我想存储枚举类名称和枚举值。 当我从db查询记录时,我也想重建枚举对象。

是否可以遵循任何模式或JOOQ中可以扩展以解决此问题的功能?

JOOQ支持自定义数据类型 这意味着您可以为数据库字段定义一个converter ,然后在加载时自动将其映射到您的自定义类型。 数据库字段仍然是String ,但是为该字段生成的Record将包含Field<EligibilityRule> 这意味着您不必显式存储类名。

为此,您必须在代码生成器中注册转换器(从上面的文档页面获取):

<database>

  <!-- Then, associate custom types with database columns -->
  <forcedTypes>
    <forcedType>

      <!-- Specify the Java type of your custom type. This corresponds to the Converter's <U> type. -->
      <userType>java.util.GregorianCalendar</userType>

      <!-- Associate that custom type with your converter. -->
      <converter>com.example.CalendarConverter</converter>

      <!-- Add a Java regular expression matching fully-qualified columns. Use the pipe to separate several expressions.

           If provided, both "expressions" and "types" must match. -->
      <expression>.*\.DATE_OF_.*</expression>

      <!-- Add a Java regular expression matching data types to be forced to
           have this type.

           Data types may be reported by your database as:
           - NUMBER              regexp suggestion: NUMBER
           - NUMBER(5)           regexp suggestion: NUMBER\(5\)
           - NUMBER(5, 2)        regexp suggestion: NUMBER\(5,\s*2\)
           - any other form

           It is thus recommended to use defensive regexes for types.

           If provided, both "expressions" and "types" must match. -->
      <types>.*</types>
    </forcedType>
  </forcedTypes>
</database>

另请参见JOOQ支持的自定义数据类型绑定


我明白了您的意思,在我的情况下,我没有为每个枚举创建新的数据库字段,而是将它们存储为rule_type和rule_value(key / value)对,其中键是类名,而值是枚举值。

我懂了。 不幸的是,我认为不可能以类型安全的方式执行此操作。 我相信这个答案几乎就是您要的-基于列值的特殊类型的绑定。

但是,由于您使用的是枚举,因此不能像上面的答案中那样使它们扩展超类(因为所有Enum都隐式扩展了java.lang.Enum而Java不支持多重继承)。 但是,您可以尝试稍微重构代码,并使所有枚举实现某种接口,即:

enum ProductEligibility implements Rule {...};
enum CountryEligibility implements Rule {...};

Rule为:

interface Rule { String getRuleType(); String getRuleValue(); }

然后像在docs页面中的示例或单独的链接答案中那样创建一个转换器。

当然,这也意味着Record中将有一个Field<Rule>字段,而不是枚举的特定类型。 如果这对您来说是可以接受的,则可能是可行的方法。


我没有得到这一部分, Of course, this also means that your Records would have a Field<Rule> field in them, not the specific type of the enum. 这是否意味着我仍将使用CustomConverter将两个字段分别存储在db中,rule_type和rule_value?

不会。您仍然只有一个转换器,类型为Converter<Object, Rule> 该转换器将返回要么 ProductEligibilityCountryEligibility ,但不能同时返回。

因此,如果您的数据库表具有以下内容:

eligiblity_rules
------------------
id    user    type                              value 
234   223     com.foo.bar.ProductEligibility    PRODUCT_Y
856   855     com.foo.bar.CountryEligibility    US

您的转换器看起来像这样:

public Converter<Object, Rule> converter() {
    return new Converter<Object, Rule>() {
        @Override
        public Rule from(Object t) {
            // t here refers to the "value" db field above
            if (checkIsProductEligibilityRule())
                 return ProductEligibility.fromValue(...);
            else
                return CountryEligibility.fromValue(...)
        }

        // Other converter methods
    };
}

因此,在基于JOOQ的代码中,您最终将拥有:

EligibilityRuleRecord record = dslContext.selectFrom(ELIGIBILITY_RULE).where(...).fetchOne();
Rule rule = record.getValue();

之后,如果要使用特定的规则类型,则需要检查和强制转换:

if (rule instanceof ProductEligibility) {
    ProductEligibility peRule = (ProductEligibility) rule; 
    ...
}
if (rule instanceof CountryEligibility) {
    CountryEligibility ceRule = (CountryEligibility) rule;
    ...
}
...

type数据库字段的唯一原因是选择正确的数据。 不幸的是,Java代码不知道(在编译时)类型是什么,因此,每次您想知道该字段的特定类型时,都需要在运行时进行类检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM