[英]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>
。 该转换器将返回要么 ProductEligibility
或CountryEligibility
,但不能同时返回。
因此,如果您的数据库表具有以下内容:
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.