具有多个外键的一对多实体映射作为复合主键

时间:2018-04-09 20:58:13

标签: java hibernate jpa entity-relationship entities

我通过了java持久性文档和很多Stackoverflow示例来表示这种表示。有人可以证实我这样做是正确的吗?

类型A的实例与类型C的许多实例相关联。类型B的实例与类型C的许多实例相关联.C的实例具有包含指向实体a和B的外键的复合主键。

表:

A

|------|
| A_ID |
|------|
| 1    |
| 2    |
| 3    |
| 4    |
| 5    |
|------|

其中A_ID是主键

|------|
| B_ID |
|------|
| 1    |
| 2    |
|------|

其中B_ID是主键

C

|------|------|
| A_ID | B_ID |
|------|------|
| 1    | 1    |
| 2    | 1    |
| 3    | 2    |
|------|------|

外键组合(A_ID,B_ID)是主键

实体:

@Entity
Class A {

    @Id
    @PrimaryKeyColumnName(name="A_ID")
    private Long id;


    @OneToMany(
        cascade = CascadeType.ALL,
        orphanRemoval = true,
        mappedBy="A_ID"
    )
    Collection<C> values;


    public Long getId() {
        return this.id;
    }


    public Collection<C> getValues() {
        return this.values;
    }
}


@Entity
Class B {

    @Id
    @PrimaryKeyColumnName(name="B_ID")
    private Long id;

    public Long getId() {
        return this.id;
    }
}


@Entity
Class C {

    @EmbeddedId
    private CId cId;

    public CId getCId() {
        return this.cId;
    }
}

@Embeddable
Class CId {

    @ManyToOne
    @JoinColumn(name="A_ID")
    private A a;


    @ManyToOne
    @JoinColumn(name="B_ID")
    private B b;


    public Long getA() {
        return this.a;
    }

    public Long getBId() {
        return this.b;
    }

    @Override
    public int hashCode() {
        return Objects.hash(
            this.getA().getId(),
            this.getBId().getId()
        );
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof CId)) return false;
        CId that = (CId) obj;
        return Objects.equals(this.getA().getId(),
            that.getA().getId()) &&
            Objects.equals(this.getBId().getId(),
                that.getBId().getId());
    }
}

1 个答案:

答案 0 :(得分:0)

这是JPA规范称之为“派生身份”的内容。您应该稍微不同地定义您的类。以下是代码的显着部分:

@Entity
Class A {

    @Id
    @Column(name="A_ID")
    private Long id;

    @OneToMany(
        cascade = CascadeType.ALL,
        orphanRemoval = true,
        mappedBy="a"
    )
    Collection<C> values;

    ...
}


@Entity
Class B {

    @Id
    @Column(name="B_ID")
    private Long id;

    ...
}


@Entity
Class C {

    @EmbeddedId
    private CId cId;

    @ManyToOne
    @JoinColumn(name="A_ID")
    @MapsId("aId") // maps aId attribute of embedded id
    private A a;

    @ManyToOne
    @JoinColumn(name="B_ID")
    @MapsId("bId") // maps bId attribute of embedded id
    private B b;

    ...
}

@Embeddable
Class CId {

    private Long aId; // corresponds to PK type of A

    private Long bId; // corresponds to PK type of B

    ...
}

派生身份在JPA 2.1规范2.4.1节中讨论。