JPA 复合键 + 序列
-
04-07-2019 - |
题
是否可以在普通 JPA 或 JPA+Hibernate 扩展中声明一个组合键,其中组合键的元素是一个序列?
这是我的复合类:
@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;
}
//...
}
我已经提供了以下值 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");
当我打电话时 em.persist(i1
),我希望 canonicalId
生成并插入集成。
这可能吗?如果可以的话,简单的方法是什么?(我不喜欢使用应用程序提供的密钥或本机 sql)。
解决方案
我认为普通的JPA无法做到这一点。
其他提示
JPA 2 规范中未指定对复合 PK 使用 @GenerateValue。
来自 JPA 规范:
11.1.17 生成值注解
生成值注释为主要密钥值的生成策略提供了规范。生成值注释可以与ID注释一起应用于实体或映射的超类的主键属性或字段。[97]仅需支持简单的主键即可使用生成值注释的使用。对于派生的主要密钥,不支持生成值注释的使用。
请注意,在不同的场景下,您可以拥有一个具有使用 @GenerateValue 的简单 PK (@Id) 的父实体,然后拥有一个具有复合 PK 的子实体,其中包含从父实体生成的 Id 以及另一列。
- 为子实体提供与父实体的 @ManyToOne 关系,以便它继承 FK 列中生成的 ID。
- 然后通过针对实体指定的 @IdClass 以及实体内的两个 @Id 列,为子级提供复合 PK。
@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;
@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 {
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) { //... }
}
试试这样:
@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;
}
通过这种方式,您可以使用表格而不是使用序列。
我注意到你的构建是一个像这样的复合主键 example 。当我在自己的数据库中查找类似的问题时,我想知道是否可以直接调用sql:
select nextval('hibernate_sequence')
我认为那会欺骗; - )
不隶属于 StackOverflow