简体   繁体   English

JPA复合键+序列

[英]JPA Composite Key + Sequence

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 , nativeId and nativeKey . 我已经提供了applicationentitynativeIdnativeKey I want to construct an entity like the one below: 我想构建一个如下所示的实体:

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 canonicalId is 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)。

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

Using @GeneratedValue for composite PKs is not specified withi JPA 2 spec. 在JPA 2规范中未指定使用@GeneratedValue进行复合PK。

From the JPA spec: 从JPA规范:

11.1.17 GeneratedValue Annotation 11.1.17 GeneratedValue注释

The GeneratedValue annotation provides for the specification of generation strategies for the values of primary keys. GeneratedValue注释提供了主键值的生成策略的规范。 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] GeneratedValue注释可以与Id注释一起应用于实体的主键属性或字段或映射的超类。[97] The use of the GeneratedValue annotation is only required to be supported for simple primary keys. 仅需要支持简单主键使用GeneratedValue注释。 Use of the GeneratedValue annotation is not supported for derived primary keys. 派生主键不支持使用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. 为子实体提供@ManyToOne关系,以便它在FK列中继承生成的ID。
  • Then give the child a composite PK, via @IdClass specified against the entity, plus two @Id columns within the entity. 然后通过针对实体指定的@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) { //... }
}

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. 通过这种方式,您可以使用表格而不是使用序列。

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')

I suppose that would be cheating though ;-) 我想那会欺骗;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM