JPA复合键+序列
在普通的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规范中未指定使用@GeneratedValue用于复合PK。
从JPA规范:
11.1.17 GeneratedValue注释
GeneratedValue注释提供了主键值的生成策略的规范。 GeneratedValue注释可以与Id注释一起应用于实体或映射超类的主键属性或字段。[97] 仅需要支持简单主键使用GeneratedValue注释。 派生主键不支持使用GeneratedValue注释。
请注意,在不同的场景下,您可以拥有一个使用@GeneratedValue的简单PK(@Id)的父实体,然后让一个子实体具有一个复合PK,其中包含来自父级的生成的Id以及另一列。
- 为子实体提供@ManyToOne关系,以便它在FK列中inheritance生成的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; }
这样,您可以使用表格而不是使用序列。
我注意到你的构建是一个像这个例子的复合主键。 当我在我自己的数据库中查找类似的问题时,我想知道是否可以直接调用sql:
select nextval ('hibernate_sequence')
我想那会欺骗;-)