jac*_*cnr 6 hibernate one-to-one
我想要3个java类的对象之间的单向一对一关系:Person to Heart,Person to Liver.我希望对象共享相同的PK,即每个人都有相应的心脏和肝脏,其中person.person_id = heart.heart_id = liver.liver_id.我不想将3个表合并为1,因为每个表都有很多字段.这是我的代码(主要基于此问题的接受答案):
@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
}
Run Code Online (Sandbox Code Playgroud)
我设置会话并执行以下操作:
Person jack = new Person();
jack.setName("jack");
Heart heart = new Heart();
heart.setBpm(80);
Liver liver = new Liver();
liver.setHealthy(true);
Run Code Online (Sandbox Code Playgroud)
然后,如果我将person对象与它的器官连接起来并保存它,我会收到一个错误(注意:当我使用2个类时,例如Person和Heart,我得到了相同的行为):
jack.setHeart(heart);
jack.setLiver(liver);
session.save(jack);
Run Code Online (Sandbox Code Playgroud)
org.hibernate.id.IdentifierGenerationException:尝试从null一对一属性中分配id:person
但是,如果我以两种方式设置关系,它就有效:
jack.setHeart(heart);
heart.setPerson(jack);
jack.setLiver(liver);
liver.setPerson(jack);
session.save(jack);
Run Code Online (Sandbox Code Playgroud)
但对于单向关系来说,这肯定不是必需的吗?
干杯
PS.奇怪的是,当我只使用2个类(例如Person和Heart)时,我注意到它可以工作(将对象保存到DB中),而我只是设置链接:
heart.setPerson(jack);
session.save(heart);
Run Code Online (Sandbox Code Playgroud)
我不知道为什么会这样(我认为Person是父对象,因为它自动生成它自己的PK,其他人使用它;所以你应该设置它),但无论如何我无法想象如何将这种工作方法应用到我的3级情境......
我不想告诉你这个,但你在那里有双向关系.该人提到了心脏和肝脏,每个人都有一个参考人的参考.您在Heart和Liver的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() { ...}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以稍微更改我们的实体对象以简化连接两侧的连接,例如:
@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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7265 次 |
| 最近记录: |