【发布时间】:2011-02-14 15:44:06
【问题描述】:
我正在寻找使用 JPA 映射枚举的不同方法。我特别想设置每个枚举条目的整数值,并且只保存整数值。
@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {
public enum Right {
READ(100), WRITE(200), EDITOR (300);
private int value;
Right(int value) { this.value = value; }
public int getValue() { return value; }
};
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "AUTHORITY_ID")
private Long id;
// the enum to map :
private Right right;
}
一个简单的解决方案是使用带有 EnumType.ORDINAL 的 Enumerated 注解:
@Column(name = "RIGHT")
@Enumerated(EnumType.ORDINAL)
private Right right;
但在这种情况下,JPA 映射的是枚举索引 (0,1,2),而不是我想要的值 (100,200,300)。
我发现的这两个解决方案似乎并不简单......
第一个解决方案
解决方案proposed here 使用@PrePersist 和@PostLoad 将枚举转换为其他字段并将枚举字段标记为瞬态:
@Basic
private int intValueForAnEnum;
@PrePersist
void populateDBFields() {
intValueForAnEnum = right.getValue();
}
@PostLoad
void populateTransientFields() {
right = Right.valueOf(intValueForAnEnum);
}
第二种解决方案
第二个解决方案proposed here 提出了一个通用的转换对象,但仍然显得笨重且面向hibernate(@Type 在Java EE 中似乎不存在):
@Type(
type = "org.appfuse.tutorial.commons.hibernate.GenericEnumUserType",
parameters = {
@Parameter(
name = "enumClass",
value = "Authority$Right"),
@Parameter(
name = "identifierMethod",
value = "toInt"),
@Parameter(
name = "valueOfMethod",
value = "fromInt")
}
)
还有其他解决办法吗?
我有几个想法,但我不知道它们是否存在于 JPA 中:
- 在加载和保存授权对象时使用授权类右成员的setter和getter方法
- 一个等效的想法是告诉 JPA Right enum 将 enum 转换为 int 并将 int 转换为 enum 的方法是什么
- 因为我使用的是 Spring,有没有办法告诉 JPA 使用特定的转换器(RightEditor)?
【问题讨论】:
-
使用ORDINAL很奇怪,有时有人会改变枚举中项目的位置,数据库会变成灾难
-
不会同样适用于使用名称 - 有人可能会更改枚举名称并且他们再次与数据库不同步...
-
我同意@NatashaKP。不要使用序数。换个名字,就没有这回事了。您实际上是在删除旧枚举并添加一个具有新名称的新枚举,所以是的,任何存储的数据都会不同步(语义,也许是 :P )。
-
是的,我知道有 5 个解决方案。请参阅下面的答案,我有一个详细的答案。