java JPA 复合键 + 序列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/242914/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA Composite Key + Sequence
提问by Miguel Ping
Is it possible in plain JPA or JPA+Hibernate extensions to declare a composite key, where an element of the composite key is a sequence?
是否可以在普通的 JPA 或 JPA+Hibernate 扩展中声明一个复合键,其中复合键的一个元素是一个序列?
This is my composite class:
这是我的复合类:
@Embeddable
public class IntegrationEJBPk implements Serializable {
//...
@ManyToOne(cascade = {}, fetch = FetchType.EAGER)
@JoinColumn(name = "APPLICATION")
public ApplicationEJB getApplication() {
return application;
}
@Column(name = "ENTITY", unique = false, nullable = false, insertable = true, updatable = true)
public String getEntity() {
return entity;
}
@GeneratedValue(strategy = GenerationType.AUTO, generator = "INTEGRATION_ID_GEN")
@SequenceGenerator(name = "INTEGRATION_ID_GEN", sequenceName = "OMP_INTEGRATION_CANONICAL_SEQ")
@Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getCanonicalId() {
return canonicalId;
}
@Column(name = "NATIVE_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getNativeId() {
return nativeId;
}
@Column(name = "NATIVE_KEY", unique = false, nullable = false, insertable = true, updatable = true)
public String getNativeKey() {
return nativeKey;
}
//...
}
I already supply the values for application, entity, nativeIdand nativeKey. I want to construct an entity like the one below:
我已经提供的值application,entity,nativeId和nativeKey。我想构建一个如下所示的实体:
IntegrationEJB i1 = new IntegrationEJB();
i1.setIntegrationId(new IntegrationEJBPk());
i1.getIntegrationId().setApplication(app1);
i1.getIntegrationId().setEntity("Entity");
i1.getIntegrationId().setNativeId("Nid");
i1.getIntegrationId().setNativeKey("NK");
And when I call em.persist(i1), I want that the canonicalIdis generated and the integration is inserted.
当我调用em.persist(i1) 时,我希望canonicalId生成并插入集成。
Is this possible? If so, what's the simple way? (I prefer not to use application-provided keys or native sql).
这可能吗?如果是这样,简单的方法是什么?(我不喜欢使用应用程序提供的键或本机 sql)。
采纳答案by Miguel Ping
I believe that this is not possible with plain JPA.
我相信这对于普通的 JPA 是不可能的。
回答by Glen Best
Using @GeneratedValue for composite PKs is not specified withi JPA 2 spec.
在 JPA 2 规范中未指定对复合 PK 使用 @GeneratedValue。
From the JPA spec:
从 JPA 规范:
11.1.17 GeneratedValue Annotation
The GeneratedValue annotation provides for the specification of generation strategies for the values of primary keys. The GeneratedValue annotation may be applied to a primary key property or field of an entity or mapped superclass in conjunction with the Id annotation.[97] The use of the GeneratedValue annotation is only required to be supported for simple primary keys. Use of the GeneratedValue annotation is not supported for derived primary keys.
11.1.17 生成值注解
GeneratedValue 注释提供了主键值生成策略的规范。GeneratedValue 注释可以与 Id 注释一起应用于实体或映射超类的主键属性或字段。 [97] GeneratedValue 注解的使用只需要支持简单的主键。派生主键不支持使用 GeneratedValue 注释。
Note that under a different scenario, you can have a parent entity with a simple PK (@Id) that uses @GeneratedValue, and then have a child entity that has a composite PK that includes the generated Id from the parent, plus another column.
请注意,在不同的情况下,您可以拥有一个带有使用 @GeneratedValue 的简单 PK (@Id) 的父实体,然后拥有一个具有复合 PK 的子实体,该复合 PK 包括从父级生成的 Id 以及另一列。
- Give the child a @ManyToOne relationship to the parent entity, so that it inherits the generated ID in a FK column.
- Then give the child a composite PK, via @IdClass specified against the entity, plus two @Id columns within the entity.
- 为子实体赋予与父实体的 @ManyToOne 关系,以便它继承 FK 列中生成的 ID。
- 然后通过针对实体指定的@IdClass 以及实体内的两个@Id 列为孩子提供一个复合PK。
@Entity public class ParentEntity {
@Entity public class ParentEntity {
@Id
@GenerateValue(IDENTITY) // If using DB auto-increment or similar
int id;
// ...
}
@Entity @IdClass(ChildId.class) public class ChildEntity { // The child table will have a composite PK: // (parent_ID, child_name) @Id @ManyToOne int parentEntity;
@Entity @IdClass(ChildId.class) public class ChildEntity { // The child table will have a composite PK: // (parent_ID, child_name) @Id @ManyToOne int parentEntity;
@Id
String childName;
String favoriteColor; // plus other columns
// ...
}
// child Id attributes have the same name as the child entity // however the types change to match the underlying PK attributes // (change ParentEntity to int) public class ChildId implements Serializable {
// child Id attributes have the same name as the child entity // however the types change to match the underlying PK attributes // (change ParentEntity to int) public class ChildId implements Serializable {
int parentEntity;
String childName;
public ChildId() { //... }
// Add extra constructor & remove setter methods so Id objects are immutable
public ChildId(int parentEntity, String childName) { //... }
public int getParentEntity() { //... }
// make Id objects immutable:
// public void setParentEntity(int parentEntity) { //... }
public String getChildName() { //... }
// public void setChildName(String childName) { //... }
}
回答by Petriborg
I notice that it appears your building a composite primary key like this example. While I was poking at a similar problem in my own database I wondered if maybe you could call the sql directly like:
我注意到您似乎构建了一个像这个例子一样的复合主键。当我在自己的数据库中寻找类似的问题时,我想知道您是否可以像这样直接调用 sql:
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
I suppose that would be cheating though ;-)
我想那会是作弊;-)
回答by sakana
Try like this:
像这样尝试:
@TableGenerator(name = "canonicalKeys", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "canonicalKeys")
@Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getCanonicalId() {
return canonicalId;
}
In this way instead of using a sequence you can use a table.
通过这种方式,您可以使用表格而不是使用序列。

