由于缺少SQL枚举类型,不幸的是有些流行的数据库设计模式似乎是为所有枚举值创建一个表(感谢您的链接,Nathan).多年来我看到了很多这种变化,但我目前正在努力解决的问题看起来像这样:
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
Run Code Online (Sandbox Code Playgroud)
然后将其用于此类 - 例如在人员表中:
ID | NAME | TYPE
----+----------+------
1 | Jane Doe | 19
Run Code Online (Sandbox Code Playgroud)
这意味着Jane是一个管理器,因为19是enum表中人员类型"manager"的主键.
使用JPA(2.1),是否有一种优雅的方法将此构造映射到propper 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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果CDI在@Converters 中可用,我会和它一起生活- 但静态构造测试是一场噩梦.
作为参考,这就是我解决问题的方法。正确的 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 { }
Run Code Online (Sandbox Code Playgroud)
因此,枚举值的 getter 和 setter 具有不同的类型,并且设置值需要引用实体,这会进一步破坏代码。
| 归档时间: |
|
| 查看次数: |
5271 次 |
| 最近记录: |