Search code examples
javahibernateannotationshibernate-mappingforeign-key-relationship

Hibernate interprets two foreign key relations as composite primary key(MappingException). Why?


I have three classes: A has a OneToMany relationsship with B and B has a OneToMany relationship with C. I want to have a Map in Class A containing B_ID as key and the B object as value. B should contain C objects in a list. Joins are done with A_ID<>B_A_ID and B_RUN_ID<>C_RUN_ID.

Class A:

class A{
@Id
@Column(name = "A_ID")
private Long aId;

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "T_B",
    schema = "owner",
    joinColumns = @JoinColumn(name = "B_A_ID",
            referencedColumnName = "A_ID",
            nullable = false))
@MapKeyColumn(name = "B_RUN_ID")
@Column(name = "B_STATUS")
@Enumerated(javax.persistence.EnumType.STRING)
private Map<Long, Status> trackings;

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "B_A_ID")
@MapKeyColumn(name = "B_ID")
private Map<Long,B> trackingB;
...}

Class B:

class B{
@Id
@Column(name = "B_ID")
private Long bId;

@Column(name = "B_A_ID")
private A a;

@Column(name = "B_RUN_ID", unique=true)
private long runId;

@OneToMany(mappedBy = "c_runID")
private List<C> cTrackings;
...}

Class C:

class C{
@Id
@Column(name = "C_ID",unique=true)    
private long id;

@ManyToOne
@JoinColumn(name = "B_RUN_ID")
private B c_runData;

@Column(name = "EX_ID")
private long externalId;
...}

I get the following error at deploy:
MappingException: ForeignKey "C[B_RUN_ID]" must have same number of columns as the referenced primary key "B[B_A_ID,B_RUN_ID]" My Question: Why are these foreign keys interpreted as a composite primary key? The primary key for B is the generated "B_ID".
Any help is much appreciated :)


Solution

  • Class A had a second Map as Embeddable:

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "T_B",
            schema = "owner",
            joinColumns = @JoinColumn(name = "B_A_ID",
                    referencedColumnName = "A_ID",
                    nullable = false))
    @MapKeyColumn(name = "B_RUN_ID")
    @Column(name = "B_STATUS")
    @Enumerated(javax.persistence.EnumType.STRING)
    private Map<Long, Status> trackings;
    

    The annotation @MapKeyColumn(name = "B_RUN_ID") seems to define "B_RUN_ID" as primary key.
    Also as I have researched, it is not possible to join columns that are not primary and foreign key, thus a join by B_RUN_ID is impossible. Instead I added the foreign key column "C_B_ID" to class C and joined with "B_ID".