miroque miroque -4 years ago 354
Java Question

JPA mapping annotation error org.hibernate.MappingException: Foreign key must have same number of columns as the referenced primary key

I can't propper map DB tables with JPA annotation.
db

Tables Subject and Place is ManyToMany through JoinTable.

Subject.java

@Entity
@Table(name = "SUBJECT")
public class Subject implements Serializable {
@Id
@Column(name = "SID")
private Integer sid;

@Column(name = "NAME")
private String name;

// getters and setters
}


SubjectPlace.java

@Entity
@Table(name = "SUBJECT_PLACE")
public class SubjectPlace implements Serializable {
@Id
@Column(name = "SPID")
private Integer spid;

@ManyToOne
@JoinColumn(name = "SUB_KEY") //Subject FK
private Subject subject;

@ManyToOne
@JoinColumn(name = "PLC_KEY") //Place FK
private Place place;

// getters and setters
}


Place.java

@Entity
@Table(name = "PLACE")
public class Place implements Serializable {
@Id
@Column(name = "PID")
private Integer pid;

@Column(name = "NAME")
private String name;

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name = "SUBJECT_PLACE",
joinColumns = { @JoinColumn(name = "PLC_KEY", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "SUB_KEY", nullable = false, updatable = false) })
private Set<Subject> subjects;

// getters and setters
}


But than I need to link Person with Subject in selected Places. I mean that each Place has its own collection of Subject. And a Person have link to Subject whitch resides in particular Place.

like This:

Subject (M) -- (M) Place
through JoinTable
Subject (1) -- (M) Subject_Place (M) -- (1) Place


Person (M) -- (M) Subject_Place
through JoinTable
Person (1) -- (M) Person_Subject_Place (M) -- (1) Subject_Place


Person.java

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {
@Id
@Column(name = "PRSID")
private Integer prsid;

@Column(name = "NAME")
private String name;

// How to annotate this code?
// I experience problem in this part of code
@OneToMany
@JoinColumn(name="SPID_KEY")
private List<SubjectPlace> subjectPlaces;

// getters and setters
}


PersonSubjectPlace.java

@Entity
@Table(name = "PERSON_SUBJECT_PLACE")
public class PersonSubjectPlace implements Serializable {
@Id
@Column(name = "PSPID") // Person_Subject_Place ID
private Integer pspid;

@ManyToOne
@JoinColumn(name = "PER_KEY") //Person FK
private Person person;

// How to annotate this code?
// I experience problem in this part of code
@ManyToOne
@JoinColumn(name = "SPID_KEY") //Subject_Place FK
private SubjectPlace subjectPlace;

// getters and setters
}


And when I try so get Persons and its Subjects, I get this error:
Caused by: org.hibernate.MappingException: Foreign key (FK2C3B79384AABC975:PERSON_SUBJECT_PLACE [SPID_KEY])) must have same number of columns as the referenced primary key (SUBJECT_PLACE [PLC_KEY,SUB_KEY])


What, How shoul I map?

Answer Source

In your OneToMany mapping you don't need to specify the foreign key, you just need to use mappedBy property to refer your mapping object, you can learn more about it in OneToMany Mapping Documentation, and here's what you need to map Person and PersonSubjectPlace entities:

In your Person class:

@OneToMany(mappedBy="person")
private List<PersonSubjectPlace> personsubjectPlaces;

In your PersonSubjectPlace class:

@ManyToOne
@JoinColumn(name="PRSID") //Specify the primary key of Person
private Person person;

For further information about the difference between JoinColumn and mappedBy you can take a look at this answer.

EDIT:

For the mapping between SubjectPlace and PersonSubjectPlace:

In your SubjectPlace class:

@OneToMany(mappedBy="subjectPlace")
private List<PersonSubjectPlace> personsubjectPlaces;

In your PersonSubjectPlace class:

@ManyToOne
@JoinColumn(name="SPID") //Specify the primary key of SubjectPerson
private SubjectPlace subjectPlace;

Note:

The best approach to map those classes is to use @JoinTable between Person and SubjectPlace, take a look at this @JoinTable example, because PersonSubjectPlace is pratically an asociation-entity between Person and SubjectPlace.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download