如何在JPA中映射具有固定值的枚举?
如何在JPA中映射具有固定值的枚举?
我正在寻找使用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)。
我找到的两种解决方案似乎都不简单...
第一个解决方案
一个解决方案,在这里提出,使用@PrePersist和@PostLoad将枚举转换为另一个字段,并将枚举字段标记为瞬态:
@Basic private int intValueForAnEnum; @PrePersist void populateDBFields() { intValueForAnEnum = right.getValue(); } @PostLoad void populateTransientFields() { right = Right.valueOf(intValueForAnEnum); }
第二个解决方案
第二个解决方案提出了一个通用的转换对象,但仍然显得笨重,而且是面向Hibernate的(Java EE中貌似不存在@Type):
@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中:
- 在加载和保存Authority对象时使用Authority类的正确成员的setter和getter方法
- 一个等效的想法是告诉JPA Right枚举的方法,将枚举转换为int和int转换为枚举
- 因为我使用Spring,有没有办法告诉JPA使用特定的转换器(RightEditor)?
admin 更改状态以发布 2023年5月23日
现在使用JPA 2.1可以实现:
@Column(name = "RIGHT") @Enumerated(EnumType.STRING) private Right right;
更多细节:
在JPA 2.1之前的版本中,JPA仅提供通过枚举的name
或ordinal
处理枚举的两种方法,并且标准的JPA不支持自定义类型。所以:
- 如果您想进行自定义类型转换,则必须使用提供程序扩展(使用Hibernate的
UserType
,EclipseLink的Converter
等)(第二种解决方案)。或者 - 您必须使用@PrePersist和@PostLoad技巧(第一种解决方案)。或者
- 在getter和setter上使用注释,以获取并返回
int
值。或者 - 在实体级别使用整数属性,并在getter和setter中执行翻译。
我会举例说明最后一种选择(这是一个基本实现,根据需要进行调整):
@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; } public static Right parse(int id) { Right right = null; // Default for (Right item : Right.values()) { if (item.getValue()==id) { right = item; break; } } return right; } }; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "AUTHORITY_ID") private Long id; @Column(name = "RIGHT_ID") private int rightId; public Right getRight () { return Right.parse(this.rightId); } public void setRight(Right right) { this.rightId = right.getValue(); } }