17

是否可以在普通 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;
    }

    //...
}

我已经提供了applicationentitynativeId的值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)。

4

4 回答 4

3

我相信这对于普通的 JPA 是不可能的。

于 2009-02-24T20:49:43.110 回答
2

JPA 2 规范未指定将 @GeneratedValue 用于复合 PK。

从 JPA 规范:

11.1.17 GeneratedValue注解

GeneratedValue 注释提供了主键值生成策略的规范。GeneratedValue 注释可以与 Id 注释一起应用于实体或映射超类的主键属性或字段。 [97] 仅需要简单主键支持使用 GeneratedValue 注释。派生的主键不支持使用 GeneratedValue 注释。

请注意,在不同的情况下,您可以拥有一个具有使用 @GeneratedValue 的简单 PK (@Id) 的父实体,然后拥有一个具有复合 PK 的子实体,该复合 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) { //... }
}
于 2012-10-15T02:16:57.627 回答
1

试试这样:

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

通过这种方式,您可以使用表格而不是使用序列。

于 2008-10-28T17:00:18.173 回答
1

我注意到您似乎在构建一个像此示例一样的复合主键。当我在自己的数据库中解决类似的问题时,我想知道您是否可以像这样直接调用 sql:

select nextval ('hibernate_sequence')

我想那会作弊;-)

于 2009-03-30T15:00:28.873 回答