gpt4 book ai didi

java - JPA 和枚举表(又名 "the one true lookup table")

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:57:53 25 4
gpt4 key购买 nike

问题

由于缺少 SQL 枚举类型,不幸的是有点流行的数据库设计模式似乎是创建 one table for all enum values (谢谢你的链接,内森)。多年来,我看到过很多这种情况,但我目前正在努力解决的问题看起来像这样:

 ID  | ENUM        | VALUE
-----+-------------+----------
1 | DAY_OF_WEEK | SUNDAY
2 | DAY_OF_WEEK | MONDAY
...
7 | DAY_OF_WEEK | SATURDAY
...
18 | PERSON_TYPE | EMPLOYEE
19 | PERSON_TYPE | MANAGER

然后像这样使用 - 例如在人员表中:

 ID | NAME     | TYPE
----+----------+------
1 | Jane Doe | 19

表示 Jane 是一名经理,因为 19 是枚举表中人员类型“经理”的主键。

问题

使用 JPA (2.1),是否有一种优雅的方法将此构造映射到适当的 Java 枚举?

重要:我的“枚举表”有很多版本,它们具有不同的主键值,即“经理”有时可能是第 19 行,但有时排#231。但是,这些值在运行时永远不会改变。不幸的是,更改数据库架构也不是一种选择,但使用任何 JPA 提供程序的专有功能都是一种选择。

有效的方法

我实际上找到了一个有效的解决方案,但对我来说太老套了:

public enum PersonType { EMPLOYEE, MANAGER }

@Table(name="PERSONS") @Entity public class Persons {
@Id @Column(name="ID") long id;
@Column(name="NAME") String name;
@Convert(converter = PtConv.class) @Column(name="TYPE") PersonType type;
// ...
}

@Converter public class PtConv implements AttributeConverter<PersonType, Integer> {
// In a static initializer run a JDBC query to fill these maps:
private static Map<Integer, PersonType> dbToJava;
private static Map<PersonType, Integer> javaToDb;

@Override public Integer convertToDatabaseColumn(PersonType attribute) {
return javaToDb.get(attribute);
}

@Override public PersonType convertToEntityAttribute(Integer dbData) {
return dbToJava.get(dbData);
}
}

如果 CDI 在 @Converter 中可用,我会忍受这种情况 - 但静态构造测试是一场噩梦。

最佳答案

作为引用,这是我解决问题的方法。正确的 Java 枚举是我的偏好,我会接受任何比这更好的答案。

@Table(name="PERSONS") @Entity public class Persons {
@Id @Column(name="ID") long id;
@Column(name="NAME") String name;
@Column(name="TYPE") BaseEnum type; // known to be "PersonTypeEnum"

public PersonType getType() {
switch(type.getValue()) {
case "EMPLOYEE": return PersonType.EMPLOYEE;
case "MANAGER": return PersonType.MANAGER;
}
throw new IllegalStateException();
}

public void setType(PersonTypeEnum type) {
this.type = type;
}
// ...
}

@Entity @Inheritance @DiscriminatorColumn(name="ENUM") @Table(name="ENUMS")
public abstract class BaseEnum {
@Id private int id;
@Column(name="VALUE") String value;
// ...
}

@Entity @DiscriminatorValue("PERSON_TYPE")
public class PersonTypeEnum extends BaseEnum { }

因此枚举值的 getter 和 setter 具有不同的类型,并且设置值需要引用实体,这进一步破坏了代码。

关于java - JPA 和枚举表(又名 "the one true lookup table"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26393607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com