使用枚举作为 id

发布于 2024-09-19 08:53:25 字数 628 浏览 3 评论 0原文

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

所以我的问题是:

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

Using JPA, can we define an enum as id of an entity?

I've tried the following:

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

}

Using OpenJPA, it complains:

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.

So my questions are:

  • should we able to use enum as id for an entity on JPA? (i.e. there is a bug in OpenJPA)
  • or do I make a mistake somewhere?
  • and is there any workaround for such problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

子栖 2024-09-26 08:54:39

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

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

Do you really want to do this? This construct doesn't allow changing the database enum keys without updating the enum in the code (fail on load), nor the other way around (constraint failure). Why don't you just create an AssetType table with int pk and name, and make the Adkeys have a foreign key to AssetType.id as pk?

You can load the AssetTypes from the db on startup if you need to enumerate them in your app.

贱人配狗天长地久 2024-09-26 08:54:24

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

OpenJPA is the only JPA provider that does not support this.
See Support Enum as Primary Key Type

情话已封尘 2024-09-26 08:54:05

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

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

添加独立的ID列即可解决问题。

No, you can't use enums as ID because JPA doesn't allow to define your own mapping for ID columns (they must be int or long or something that JPA can create with new).

IDs must not be the business key (in your case: the type). Using the business key as an ID is a common mistake in DB designs and should be avoided because it will cause all kinds of problems later.

Add an independent ID column to solve the problem.

一个人的旅程 2024-09-26 08:53:55

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

2.1.4 主键和实体身份

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

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

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

The JPA spec doesn't say this is possible:

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.

If you really want to have a compile-time fixed number of records for a given entity, you can use a String or int primary key and assign it AssetType.FOO.name() or AssetType.FOO.ordinal()

And non-portable here means that some persistence provider may support other things, but it might not work for another provider. As with the enum - if the persistence provider has special support for it, that does not try to instantiate it, but rather processes it specially after checking if class.isEnum(), then it might work. But it seems your persistence provider doesn't do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文