使用enum作为id

nan*_*nda 6 java jpa openjpa

使用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;
   }

}
Run Code Online (Sandbox Code Playgroud)

使用OpenJPA,它抱怨:

org.apache.openjpa.persistence.ArgumentException:该ID级别"类aa.AssetType"按类型"类aa.Adkeys"规定不具有公共的无参数的构造.

所以我的问题是:

  • 我们是否应该使用枚举作为JPA上实体的id?(即OpenJPA中存在错误)
  • 或者我在某个地方犯了错误?
  • 这个问题是否有解决方法?

Boz*_*zho 8

JPA规范并未说明这是可能的:

2.1.4主键和实体标识

主键(或复合主键的字段或属性)应为以下类型之一:任何Java基本类型; 任何原始包装类型; java.lang.String中; java.util.Date; java.sql.Date.但是,通常,不应在主键中使用近似数字类型(例如,浮点类型).主键使用非这些类型的实体将不可移植.

如果你真的想记录编译时固定数目对于一个给定的实体,您可以使用一个Stringint主键,将其指定AssetType.FOO.name()AssetType.FOO.ordinal()

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


Aar*_*lla 5

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

ID不能是业务密钥(在您的情况下为类型)。在数据库设计中,使用业务密钥作为ID是常见错误,应避免使用,因为以后会引起各种问题。

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