我已经在stackoverflow和其他几个在线教程中经历了几个Q / As,以找到我在下面描述的问题中完全没有的内容。
背景: 我正在学习在我的Android应用程序中使用restful API,因此,我编写了一个简单的医患管理应用程序。医生和他的病人之间存在一对多的关系。即一位医生可以有很多病人。
问题: 我正在使用一个用户表来维护所有用户信息,即医生和病人。此表中维护了基本信息,此表还用于确定尝试登录的用户类型,以便显示适当的屏幕。以下是该表的实体的样子:
@Entity
public class ConcreteUser implements User{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name= "USER_ID")
private long id;
private String name;
private String email;
private int age;
private SEX sex;
private String accessLevel;
public ConcreteUser() {
}
// gettersand setters here
}
此实体与维护医生和患者实体的表具有一对一的关系。如前所述,医生和患者实体之间存在一对一的关系。以下是这两个实体的外观:
@Entity
public class PatientEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "PATIENT_RECORD_ID")
private long recordId;
// specify this as a foreign key from ConcreteUser entity
@OneToOne(cascade = CascadeType.ALL) /*CascadeType.ALL should not be required according to almost all the tutorials I have seen - But I always get unsaved transient object error if I don't do this and try to save a patient entity */
@JoinColumn(name="USER_ID")
private ConcreteUser patient;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "DOCTOR_RECORD_ID")
@JsonBackReference
private DoctorEntity doctor;
public PatientEntity() {
}
public void setDoctor(DoctorEntity doctor) {
this.doctor = doctor;
//if(!doctor.getPatients().contains(this)){
// doctor.addPatient(this);
//}
/* Commented out code always leads to stack overflow error */
/* although, according to tutorial in the link below, this code is necessary */
/* http://en.wikibooks.org/wiki/Java_Persistence/OneToMany */
}
// getters and setters are not shown
}
最后,这是我的医生实体:
@Entity
public class DoctorEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "DOCTOR_RECORD_ID")
private long recordId;
// specify this as a foreign key from ConcreteUser entity
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="USER_ID")
private ConcreteUser doctor;
@OneToMany(mappedBy = "doctor", cascade = CascadeType.ALL)
@JsonManagedReference
private Collection<PatientEntity> patients = new ArrayList<PatientEntity>();
public DoctorEntity() {
}
public boolean addPatient(PatientEntity p) {
boolean status = false;
status = patients.add(p);
//if (p.getDoctor() != this) {
// p.setDoctor(this);
//}
return status;
}
public boolean removePatient(PatientEntity p) {
boolean status = false;
status = patients.remove(p);
//if (p.getDoctor() != this) {
// p.setDoctor(null);
//}
return status;
}
// getters and setters are not shown. Same problem with the commented out code as described above
}
现在测试这样一个事实:当PatientEntity的POJO对象可以保存并且它保留信息时,我使用以下测试用例:
@Test
public void TestPatientDoctorManyToOne() throws Exception{
PatientEntity p1 = TestData.getPatientEntity(patient1);
DoctorEntity d = TestData.getDoctorEntity(doctor);
p1.setDoctor(d);
p1 = patientService.addPatient(p1);
assertNotNull(p1);
PatientEntity p2 = patientService.getPatientById(p1.getRecordId());
assertNotNull(p2);
assertNotNull(p2.getDoctor());
assertEquals(p1.getRecordId(), p2.getRecordId());
assertEquals(p1.getDoctor().getRecordId(), p2.getDoctor().getRecordId());
assertEquals(p1.getDoctor().getDoctor().getEmail(), p2.getDoctor().getDoctor().getEmail());
}
在上述测试案例中,assertNotNull(p2.getDoctor());
断言失败,因为返回的患者实体根本不包含医生对象。
这是日志:
Outgoing:
"{"recordId":0,"patient":{"id":0,"name":"Patient-0ee1407e-2d2b-4c6c-a57b-e2fad24fafa5","email":"0ee1407e-2d2b-4c6c-a57b-e2fad24fafa5","age":50,"sex":"MALE","accessLevel":"patient"},"doctor":{"recordId":0,"doctor":{"id":0,"name":"Doctor-f025c8ce-8c31-4681-b673-a9e322dccf5a","email":"f025c8ce-8c31-4681-b673-a9e322dccf5a","age":50,"sex":"MALE","accessLevel":"doctor"},"patients":[]}}"
Incoming:
{"recordId":16,"patient":{"id":33,"name":"Patient-0ee1407e-2d2b-4c6c-a57b-e2fad24fafa5","email":"0ee1407e-2d2b-4c6c-a57b-e2fad24fafa5","age":50,"sex":"MALE","accessLevel":"patient"}}
如您所见,返回的对象根本没有Doctor实体。
但是,当我尝试将医生实体与其中的患者一起保存时,可以毫无问题地保存。即以下测试用例通过:
@Test
public void testDoctorPatientOneToMany() throws Exception {
PatientEntity p1 = TestData.getPatientEntity(patient1);
PatientEntity p2 = TestData.getPatientEntity(patient2);
DoctorEntity d = TestData.getDoctorEntity(doctor);
d.addPatient(p1);
d.addPatient(p2);
d = doctorService.addDoctor(d);
DoctorEntity d2 = doctorService.getDoctorById(d.getRecordId());
assertNotNull(d2);
assertEquals(d2.getRecordId(), d.getRecordId());
assertEquals(d2.getDoctor().getEmail(), d.getDoctor().getEmail());
}
上述测试用例的交易: 传出:
"{"recordId":17,"doctor":{"id":43,"name":"Doctor-e4baeee7-eaaa-443e-8845-e0b12d7be82f","email":"e4baeee7-eaaa-443e-8845-e0b12d7be82f","age":50,"sex":"MALE","accessLevel":"doctor"},"patients":[{"recordId":21,"patient":{"id":44,"name":"Patient-d8aab5ad-d3d9-4442-b8de-678de9e3b1ce","email":"d8aab5ad-d3d9-4442-b8de-678de9e3b1ce","age":50,"sex":"MALE","accessLevel":"patient"}},{"recordId":22,"patient":{"id":45,"name":"Patient-5c9cfa3c-ee79-4aea-a193-4d8762f58431","email":"5c9cfa3c-ee79-4aea-a193-4d8762f58431","age":50,"sex":"MALE","accessLevel":"patient"}}]}[\r][\n]"
Incoming:
{"recordId":17,"doctor":{"id":43,"name":"Doctor-e4baeee7-eaaa-443e-8845-e0b12d7be82f","email":"e4baeee7-eaaa-443e-8845-e0b12d7be82f","age":50,"sex":"MALE","accessLevel":"doctor"},"patients":[{"recordId":21,"patient":{"id":44,"name":"Patient-d8aab5ad-d3d9-4442-b8de-678de9e3b1ce","email":"d8aab5ad-d3d9-4442-b8de-678de9e3b1ce","age":50,"sex":"MALE","accessLevel":"patient"}},{"recordId":22,"patient":{"id":45,"name":"Patient-5c9cfa3c-ee79-4aea-a193-4d8762f58431","email":"5c9cfa3c-ee79-4aea-a193-4d8762f58431","age":50,"sex":"MALE","accessLevel":"patient"}}]}
我为帖子道歉,但我想我已经耗尽了所有的资源。我绝对崇拜那些决定看一眼并指出问题所在的人。在这一点上,我甚至不确定我是否正确测试这件事,或者我的期望是正确的。
答案 0 :(得分:1)
这是因为在DoctorEntity类中指定了mappedBy =“doctor”
@Entity
public class DoctorEntity {
@OneToMany(mappedBy = "doctor", cascade = CascadeType.ALL)
@JsonManagedReference
private Collection<PatientEntity> patients = new ArrayList<PatientEntity>();
public DoctorEntity() {
}
}
你说DoctorEntity不再是一对多关系的拥有者。 PatientEntity是所有者。因此,在保存PatientEntity期间(在第一个测试案例中),医生实体的外键未在患者表中更新。
mappedBy
是xml格式的equivalent to specifying inverse=true
。
关注在一对多映射中指定inverse = true或inverse = false时执行查询的详细说明。