I want a unidirectional one-to-one relationship between objects of 3 java classes: Person to Heart, and Person to Liver. I want the objects to share the same PK i.e. every person has a corresponding heart and liver, where person.person_id = heart.heart_id = liver.liver_id. I do not want to merge the 3 tables into 1 because each has loads of fields. Here's my code (mostly based on the accepted answer for this question):
@Entity
public class Person {
public long personId;
private String name;
public Heart heart;
public Liver liver;
// other fields
@Id
@GeneratedValue
public long getPersonId() {return personId;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {return heart;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Liver getLiver() {return liver;}
// other getters and setters and constructors
}
@Entity
public class Heart {
private long heartId;
private int bpm;
private Person person;
// other fields
@Id
@GenericGenerator(
name = "generator",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "person")
)
@GeneratedValue(generator = "generator")
public long getHeartId() {return heardId;}
@OneToOne(mappedBy="heart")
@PrimaryKeyJoinColumn
public Person getPerson() {return person;}
// other getters and setters and constructors
}
@Entity
public class Liver {
private long liverId;
private boolean healthy;
private Person person;
// other fields
// the rest uses the same hibernate annotation as Heart
}
I setup the session and do the following:
Person jack = new Person();
jack.setName("jack");
Heart heart = new Heart();
heart.setBpm(80);
Liver liver = new Liver();
liver.setHealthy(true);
Then if I link up the person object with it's organs, and save it, I get an error (NOTE: I got the same behaviour when I just used 2 classes e.g. Person and Heart):
jack.setHeart(heart);
jack.setLiver(liver);
session.save(jack);
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property: person
However it works if I set the relationship both ways:
jack.setHeart(heart);
heart.setPerson(jack);
jack.setLiver(liver);
liver.setPerson(jack);
session.save(jack);
But surely this should not be necessary for unidirectional relationships?
Cheers
ps. Oddly enough, I notice it works (saves both objects to the DB) when I just use 2 classes e.g. Person and Heart, and I just set the link the other way:
heart.setPerson(jack);
session.save(heart);
I have no idea why this works (it seems logical to me that Person is the parent object, as it auto-generates it's own PK, and the others use that; so that's all you should have to setup), but anyway I cannot figure out how to apply this working method to my 3-class situation...