我想要3个Java类的对象之间的一对一的单向关系:“人到心脏”和“人到肝脏”。我希望对象共享相同的PK,即每个人都有相应的心脏和肝脏,其中person.person_id = heart.heart_id = liver.liver_id。我不想将3个表合并为1个表,因为每个表都有很多字段。这是我的代码(主要基于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
}
我设置了 session 并执行以下操作:
Person jack = new Person();
jack.setName("jack");
Heart heart = new Heart();
heart.setBpm(80);
Liver liver = new Liver();
liver.setHealthy(true);
然后,如果我将人对象与它的器官连接起来并保存起来,则会收到错误消息(注意:当我仅使用2个类(例如人和心脏)时,我会得到相同的行为):
jack.setHeart(heart);
jack.setLiver(liver);
session.save(jack);
但是,如果我同时设置这种关系,它会起作用:
jack.setHeart(heart);
heart.setPerson(jack);
jack.setLiver(liver);
liver.setPerson(jack);
session.save(jack);
但是,对于单向关系,肯定不需要这样做吗?
干杯
ps。奇怪的是,当我仅使用2个类时,我注意到它可以工作(将两个对象都保存到数据库中)。人与心,我只是以其他方式设置了链接:
heart.setPerson(jack);
session.save(heart);
我不知道为什么这行得通(在我看来,Person是父对象,因为它自动生成自己的PK,而其他人则使用它;所以这就是您应该设置的全部),但是无论如何我都无法弄清楚了解如何将这种工作方法应用于我的3类情况...
最佳答案
我不愿意告诉您这一点,但是您在那里存在双向关系。该人对心脏和肝脏有引用,而每个人都有对人的引用。您在“心脏”和“肝脏”的Id属性上设置的注释明确表示,它们通过委派给其Person属性来获得其Id属性的值。在显示的示例中,这些示例无效,您尚未在这些家伙上设置Person属性,因此,他们显然无法获得其Id值。
您可以将此关系设置为真正的单向OneToOne,这在Hibernate批注文档中进行了说明:
@Entity
public class Body {
@Id
public Long getId() { return id; }
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {
return heart;
}
...
}
@Entity
public class Heart {
@Id
public Long getId() { ...}
}
或者,您可以稍微更改我们的实体对象,以简化连接关系的两侧,例如:
@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;}
public void setHeart(Heart heart){
this.heart = heart;
this.heart.setPerson(this);
}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Liver getLiver() {return liver;}
public void setLiver(Liver liver){
this.liver = liver;
this.liver.setPerson(this);
}
// other getters and setters and constructors
}
关于hibernate - hibernate 一对一的实体关联,并在3个类之间共享PK,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1867235/