简体   繁体   English

hibernate composite主键包含一个复合外键,如何映射这个

[英]hibernate composite Primary key contains a composite foreign key, how to map this

I searched there, and didn't find any similar topic, so I am posting a new question. 我在那里搜索,没有找到任何类似的话题,所以我发布了一个新问题。

I am working with Hibernate on an existing Database. 我正在使用现有数据库上的Hibernate。 The table structure and data we are not allowed to change. 我们不允许更改表结构和数据。 The application is reading data from the database and migrating to another datastore based on some logic. 应用程序正在从数据库中读取数据,并根据某些逻辑迁移到另一个数据存储区。

Now the problem is about a composite PK mapping. 现在问题是关于复合PK映射。 eg 例如

Table A has a composite PK. 表A具有复合PK。

Table A
--------
a1 (pk)
a2 (pk)
a3 (pk)
a4 (pk)
foo
bar
========

Table B has a composite PK too, and one part of this composite PK is A's PK, here is working as FK as well. 表B也具有复合PK,并且该复合PK的一部分是A的PK,这里也用作FK。

Table B
--------
a1 (fk,pk)
a2 (fk,pk)
a3 (fk,pk)
a4 (fk,pk)
b1 (pk)
b2 (pk)
b3 (pk)
foo
bar
========

I tried several ways, and none of them works. 我尝试了几种方法,但没有一种方法可行。 Can anyone tell a working Hibernate mapping solution? 谁能告诉一个有效的Hibernate映射解决方案? better in annotation style. 注释风格更好。

Set up A's entity object as a @ManyToOne in B's pk Class. 在B的pk类中将A的实体对象设置为@ManyToOne。

So if you have 所以,如果你有

Class A
Class APK - A's Primary Key

Class B
Class BPK - B's primary Key.

BPK will contain A as an attribute BPK将包含A作为属性

@Embeddable
public class BPK implements serializable {
  ....
  private A a;

  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumns ({
    @JoinColumn(name="...", referencedColumnName = "..."),
    @JoinColumn(name="...", referencedColumnName = "..."),
    ...
  })
  public getA() {
    return this.a;
  }
}

From the documentation 文档中

@Embeddable inherit the access type of its owning entity unless the Hibernate specific annotation @AccessType is used. @Embeddable继承其拥有实体的访问类型,除非使用Hibernate特定注释@AccessType。 Composite foreign keys (if not using the default sensitive values) are defined on associations using the @JoinColumns element, which is basically an array of @JoinColumn. 复合外键(如果不使用默认敏感值)是在使用@JoinColumns元素的关联上定义的,该元素基本上是@JoinColumn的数组。 It is considered a good practice to express referencedColumnNames explicitly. 明确表达referencedColumnNames是一种很好的做法。 Otherwise, Hibernate will suppose that you use the same order of columns as in the primary key declaration. 否则,Hibernate将假设您使用与主键声明中相同的列顺序。

If your compound primary key have only surrogate keys, use @EmbeddableId 如果复合主键只有代理键,请使用@EmbeddableId

@Embeddable
public class CompoundIdA implements Serializable {

    private Integer field0;
    private Integer field1;
    private Integer field2;
    private Integer field3;

    @Column(name="FIELD_0")
    public Integer getField0() {
        return this.field0;
    }

    @Column(name="FIELD_1")
    public Integer getField1() {
        return this.field1;
    }

    @Column(name="FIELD_2")
    public Integer getField2() {
        return this.field2;
    }

    @Column(name="FIELD_3")
    public Integer getField3() {
        return this.field3;
    }

    public boolean equals(Object o) {
        if(o == null)
            return false;

        if(!(o instanceof CompoundIdA))
            return false;

        final CompoundIdA other = (CompoundIdA) o;
        if(!(getField0().equals(other.getField0()))
            return false;

        if(!(getField1().equals(other.getField1()))
            return false;

        if(!(getField2().equals(other.getField2()))
            return false;

        if(!(getField2().equals(other.getField2()))
            return false;

        return true;
    }

    // hashcode impl

}

In ClassA, we have 在ClassA中,我们有

@Entity
public class ClassA {

    private CompoundIdA compoundIdA;

    @EmbeddedId
    public CompoundIdA getCompoundIdA() {
        return this.CompoundIdA;
    }

}

If your compound primary key have both natural and surrogate keys , use again @EmbeddableId 如果复合主键同时具有自然键和代理键 ,请再次使用@EmbeddableId

// Let's suppose field0 and field1 are both natural keys
@Entity
public class ClassA {

    private CompoundIdA compoundIdA;

    private Integer field0;
    private Integer field1;

    @EmbeddedId
    public CompoundIdA getCompoundIdA() {
        return this.CompoundIdA;
    }

    @Column(name="FIELD_0", insertable=false, updateable=false)
    public Integer getField0() {
        return this.field0;
    }

    @Column(name="FIELD_1", insertable=false, updateable=false)
    public Integer getField1() {
        return this.field1;
    }

}

Notice you have to set up insertable=false and updateable=false because more than one property share the same column. 请注意, 您必须设置insertable = false和updateable = false,因为多个属性共享同一列。 Otherwise, Hibernate will complain some errors. 否则,Hibernate会抱怨一些错误。

If your compound primary key have only natural keys, use @IdClass 如果复合主键只有自然键,请使用@IdClass

@Entity
@IdClass(CompoundIdA.class)
public class ClassA {

    private Integer field0;
    private Integer field1;
    private Integer field2;
    private Integer field3;

    @Id
    @Column(name="FIELD_0")
    public Integer getField0() {
        return this.field0;
    }

    @Id
    @Column(name="FIELD_1")
    public Integer getField1() {
        return this.field1;
    }

    @Id
    @Column(name="FIELD_2")
    public Integer getField2() {
        return this.field2;
    }

    @Id
    @Column(name="FIELD_3")
    public Integer getField3() {
        return this.field3;
    }

}

In ClassB, you can use the same approach as shown above, but if you want to define a @ManyToOne property, you have to set up insertable=false and updateable=false as follows 在ClassB中,您可以使用与上面所示相同的方法, 但是如果要定义@ManyToOne属性, 则必须设置 insertable = false和updateable = false,如下所示

@Entity
public class ClassB {

    private ClassA classA;

    @ManyToOne
    @JoinColumns ({
        @JoinColumn(name="FIELD_0", referencedColumnName="FIELD_0", insertable=false, updateable=false),
        @JoinColumn(name="FIELD_1", referencedColumnName="FIELD_1", insertable=false, updateable=false),
        @JoinColumn(name="FIELD_2", referencedColumnName="FIELD_2", insertable=false, updateable=false),
        @JoinColumn(name="FIELD_3", referencedColumnName="FIELD_3", insertable=false, updateable=false)
    })
    public ClassA getClassA() {
        return this.classA;
    }

}

regards, 问候,

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

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