8

使用 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”没有公共的无参数构造函数。

所以我的问题是:

  • 我们应该能够使用枚举作为 JPA 上实体的 id 吗?(即 OpenJPA 中有一个错误)
  • 还是我在某处犯了错误?
  • 有没有解决这个问题的方法?
4

4 回答 4

8

JPA 规范并没有说这是可能的:

2.1.4 主键和实体身份

主键(或复合主键的字段或属性)应该是以下类型之一: 任何 Java 原始类型;任何原始包装类型;java.lang.String; java.util.日期;java.sql.日期。然而,一般来说,近似数字类型(例如,浮点类型)不应该在主键中使用。主键使用非这些类型的实体将不可移植。

如果您真的想为给定实体提供编译时固定数量的记录,您可以使用 a Stringorint主键并将其分配AssetType.FOO.name()AssetType.FOO.ordinal()

这里的不可移植意味着一些持久性提供者可能支持其他东西,但它可能不适用于另一个提供者。与枚举一样 - 如果持久性提供程序对它有特殊支持,它不会尝试实例化它,而是在检查 if 之后专门处理它class.isEnum(),那么它可能会工作。但是您的持久性提供程序似乎没有这样做。

于 2010-09-15T12:53:54.683 回答
4

不,您不能使用枚举作为 ID,因为 JPA 不允许为 ID 列定义您自己的映射(它们必须是intlongJPA 可以创建的东西new)。

ID 不能是业务密钥(在您的情况下:类型)。使用业务密钥作为 ID 是 DB 设计中的常见错误,应该避免,因为它会导致以后出现各种问题。

添加一个独立的ID列来解决问题。

于 2010-09-15T12:55:51.603 回答
2

OpenJPA 是唯一不支持此功能的 JPA 提供程序。请参阅支持枚举作为主键类型

于 2011-05-28T02:09:14.443 回答
0

你真的想这样做吗?此构造不允许更改数据库枚举键而不更新代码中的枚举(加载失败),也不允许相反(约束失败)。为什么不直接创建一个带有int pk 和name 的AssetType 表,并让Adkeys 有一个AssetType.id 的外键作为pk?

如果您需要在应用程序中枚举它们,您可以在启动时从数据库加载 AssetType。

于 2010-09-15T13:08:33.337 回答