简体   繁体   中英

Entity mapping for one to many with multiple foreign keys as composite primary key

I went through java persistence documentation and a lot of Stackoverflow examples for this representation. Can someone please validate that I'm doing this correctly?

An instance of type A is associated with many instances of type C. An instance of type B is associated with many instances of type C. An instance of C has a composite primary key comprising foreign keys pointing to entities a and B.

Tables:

A

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

Where A_ID is the primary key

B

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

Where B_ID is the primary key

C

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

Where the foreign key combination (A_ID, B_ID) is the primary key

Entities:

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

This is what the JPA spec calls a "derived identity". You should define your classes slightly differently. Here are the salient bits of code:

@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

    ...
}

Derived identities are discussed in the JPA 2.1 spec in section 2.4.1.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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