使用JPA,我们可以将枚举定义为实体的id吗?
我尝试了以下内容:
public enum AssetType {
....
}
@Entity
@IdClass(AssetType.class)
public class Adkeys {
private AssetType type;
@Id
@Enumerated(EnumType.STRING)
@Column(nullable = false)
public AssetType getType() {
return type;
}
}
使用OpenJPA,它抱怨:
org.apache.openjpa.persistence.ArgumentException:由类“class aa.Adkeys”指定的id类“class aa.AssetType”没有公共的no-args构造函数。
所以我的问题是:
答案 0 :(得分:7)
JPA规范并未说明这是可能的:
2.1.4主键和实体标识
主键(或复合主键的字段或属性)应为以下类型之一:任何Java基本类型;任何原始包装类型; java.lang.String中; java.util.Date; java.sql.Date。然而,通常,不应在主键中使用近似数字类型(例如,浮点类型)。主键使用其他类型的实体将不可移植。
如果您确实希望为给定实体提供编译时固定数量的记录,则可以使用String
或int
主键并为其分配AssetType.FOO.name()
或{{ 1}}
此处不可移植意味着某些持久性提供程序可能支持其他内容,但它可能不适用于其他提供程序。与枚举一样 - 如果持久性提供程序对它有特殊支持,那么它不会尝试实例化它,而是在检查AssetType.FOO.ordinal()
后是否特别处理它,然后它可能会起作用。但似乎你的持久性提供者不会这样做。
答案 1 :(得分:4)
不,您不能将枚举用作ID,因为JPA不允许为ID列定义您自己的映射(它们必须是int
或long
或JPA可以使用{ {1}})。
ID不能是业务密钥(在您的情况下:类型)。使用业务密钥作为ID是数据库设计中的常见错误,应该避免,因为它会在以后引起各种问题。
添加一个独立的ID列来解决问题。
答案 2 :(得分:2)
OpenJPA是唯一不支持此功能的JPA提供商。 见Support Enum as Primary Key Type
答案 3 :(得分:0)
你真的想这样做吗?此构造不允许更改数据库枚举键而不更新代码中的枚举(加载失败),也不允许更改数据库枚举键(约束失败)。你为什么不用int pk和name创建一个AssetType表,并让Adkeys有一个外键到AssetType.id作为pk?
如果您需要在应用中枚举它们,可以在启动时从数据库加载AssetTypes。