有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用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)
  • 还是我在某个地方犯了错误
  • 有没有解决这个问题的办法

共 (4) 个答案

  1. # 1 楼答案

    不,不能将枚举用作ID,因为JPA不允许为ID列定义自己的映射(它们必须是intlong或JPA可以使用new创建的内容)

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

    添加一个独立的ID列以解决此问题

  2. # 3 楼答案

    你真的想这么做吗?此构造不允许在不更新代码中的枚举(加载失败)的情况下更改数据库枚举键,反之亦然(约束失败)。为什么不创建一个带有int pk和name的AssetType表,并使AdKey具有AssetType的外键呢。id为pk

    如果需要在应用程序中枚举资产类型,则可以在启动时从db加载这些资产类型

  3. # 4 楼答案

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

    2.1.4 Primary Keys and Entity Identity

    The primary key (or field or property of a composite primary key) should be one of the following types: any Java primitive type; any primitive wrapper type; java.lang.String; java.util.Date; java.sql.Date. In general, however, approximate numeric types (e.g., floating point types) should never be used in primary keys. Entities whose primary keys use types other than these will not be portable.

    如果您确实希望为给定实体拥有编译时固定数量的记录,则可以使用Stringint主键并将其分配给AssetType.FOO.name()AssetType.FOO.ordinal()

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