使用enum作为id的java
使用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: The id class "class aa.AssetType" specified by type "class aa.Adkeys" does not have a public no-args constructor.
因此,我的问题是:
- 我们应该能够使用枚举作为JPA上实体的id吗?(即OpenJPA中有一个bug)
- 还是我在某个地方犯了错误李>
- 有没有解决这个问题的办法李>
# 1 楼答案
不,不能将枚举用作ID,因为JPA不允许为ID列定义自己的映射(它们必须是
int
或long
或JPA可以使用new
创建的内容)ID不能是业务密钥(在您的情况下:类型)。使用业务密钥作为ID是DB设计中的一个常见错误,应该避免,因为它会在以后导致各种问题
添加一个独立的ID列以解决此问题
# 2 楼答案
OpenJPA是唯一不支持此功能的JPA提供商。 见Support Enum as Primary Key Type
# 3 楼答案
你真的想这么做吗?此构造不允许在不更新代码中的枚举(加载失败)的情况下更改数据库枚举键,反之亦然(约束失败)。为什么不创建一个带有int pk和name的AssetType表,并使AdKey具有AssetType的外键呢。id为pk
如果需要在应用程序中枚举资产类型,则可以在启动时从db加载这些资产类型
# 4 楼答案
JPA规范没有说这是可能的:
如果您确实希望为给定实体拥有编译时固定数量的记录,则可以使用
String
或int
主键并将其分配给AssetType.FOO.name()
或AssetType.FOO.ordinal()
这里的不可移植意味着某些持久性提供程序可能支持其他东西,但它可能不适用于其他提供程序。与枚举一样,如果持久性提供程序对它有特殊的支持,它不会尝试实例化它,而是在检查
class.isEnum()
之后专门处理它,那么它可能会工作。但您的持久性提供程序似乎没有做到这一点