使用枚举作为 id
使用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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你真的想这样做吗?此构造不允许在不更新代码中的枚举的情况下更改数据库枚举键(加载失败),也不允许更改数据库枚举键(约束失败)。为什么不直接创建一个包含 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.
OpenJPA 是唯一不支持此功能的 JPA 提供商。
请参阅支持 Enum 作为主键类型
OpenJPA is the only JPA provider that does not support this.
See Support Enum as Primary Key Type
不,您不能使用枚举作为 ID,因为 JPA 不允许为 ID 列定义您自己的映射(它们必须是
int
或long
或 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
orlong
or something that JPA can create withnew
).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.
JPA 规范并没有说这是可能的:
如果您确实希望给定实体拥有编译时固定数量的记录,则可以使用
String
或int
主键并为其分配AssetType。 FOO.name()
或AssetType.FOO.ordinal()
这里的不可移植意味着某些持久性提供程序可能支持其他内容,但它可能不适用于其他提供程序。与枚举一样 - 如果持久性提供程序对其有特殊支持,则不会尝试实例化它,而是在检查
class.isEnum()
后对其进行特殊处理,然后它可能会起作用。但您的持久性提供者似乎没有这样做。The JPA spec doesn't say this is possible:
If you really want to have a compile-time fixed number of records for a given entity, you can use a
String
orint
primary key and assign itAssetType.FOO.name()
orAssetType.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.