Spring JPA在多个嵌套实体上的双向关系



我知道过去使用spring-jpa的双向关系有很多问题,但我的情况有点不同,因为我使用了3个具有2个关系的实体来实现医疗系统

我有3个实体:医生/患者/预约

这是3个实体的代码请注意所有已实现的setter、getter和构造函数,但为了清楚起见,此处已提交

患者类别

@Entity
public class resPatient {
@Id
@GeneratedValue( strategy= GenerationType.IDENTITY )
private long code;
private String name;
private String gender;
private String email;
private String mobile;
private int age;
private String notes;

@OneToMany(mappedBy = "patient")
List<resPackageMembership> memberships;
@OneToMany(mappedBy = "patient")
List<resAppointment> appointments;
@OneToMany(fetch = FetchType.LAZY,mappedBy = "patient")
List<resMedImage> medImages;

博士级

@Entity
public class resDoctor {
@Id
@GeneratedValue( strategy= GenerationType.IDENTITY )
private long code;
private String name;
private String mobile;

private String email;
private String gender;
private int age;
private  String speciality;
@OneToMany(mappedBy = "doctor")
List<resAppointment> appointments;

预约类

@Entity
public class resAppointment {
@Id
@GeneratedValue( strategy= GenerationType.IDENTITY )
private long code;
private String speciality;
@Basic
@Temporal(TemporalType.TIMESTAMP)
private Date dateCreated;

@Basic
@Temporal(TemporalType.TIMESTAMP)
private Date dateToVisit;
private String status;
private String notes;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doctorCode")
private resDoctor doctor;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "patientCode")
private resPatient patient;

我的医疗系统应该工作的方式是,当我让病人使用我的restful控制器时,我想要所有的病人数据,包括他的预约,但这会导致一个无限循环,因为预约有医生,医生也有预约,等等。

我不能使用@JSONIGNORE,因为有两个关系我想让病人有他的预约,应该有没有预约数组的医生,并且不应该有任何病人数据,因为我已经在病人对象中了

作为一般最佳实践,建议将实体与用于其余控制器的数据传输对象分离。有了DTO,就可以更好地控制在其中包含和序列化哪些数据,以避免循环引用。如果你喜欢退房https://bootify.io,它从您的数据库模式生成DTO,但您仍然需要定义/构建自定义端点。

我最近开发了一个名为beanknife的注释处理器,它支持从任何类生成DTO。您需要通过注释进行配置。但您不需要更改原始类。此库支持在单独的类上进行配置。当然,你可以选择你想要的和不需要的房产。您可以通过config类中的static方法添加新的属性。对于您的问题:

// this will generate a DTO class named "resPatientView". 
// You can change this name using genName attribute.
@ViewOf(value=resPatient.class, includePattern = ".*")
public class PatientViewConfigure {
// here tell the processor to automatically convert the property appointments from List<resAppointment> to List<resAppointmentWithoutPatient>. 
// resAppointmentWithoutPatient is the generated class configured at the following. 
// Note, although at this moment it not exists and your idea think it is an error. 
// this code really can be compiled, and after compiled, all will ok.
@OverrideViewProperty("appointments")
private List<resAppointmentWithoutPatient> appointments;
}
// here generated a class named resAppointmentWithoutPatient whick has all properties of resAppointment except patient
@ViewOf(value=resAppointment.class, genName="resAppointmentWithoutPatient", includePattern = ".*", excludes={"patient"})
public class AppointmentWithoutPatientViewConfigure {
// the doctor property will be converted to its dto version which defined by the configure class DoctorWithoutAppointmentsViewConfigure.
@OverrideViewProperty("doctor")
private resDoctorWithoutAppointments doctor;
}
// here we generate a class which has all properties of resDoctor except appointments
@ViewOf(value=resDoctor.class, genName="resDoctorWithoutAppointments", includePattern = ".*", excludes={"appointments"})
public class DoctorWithoutAppointmentsViewConfigure {}
// in you rest controller. return the dto instead of the entities.
resPatient patient = ...
resPatientView dto = resPatientView.read(patient);
List<resPatient> patients = ...
List<resPatientView> dto = resPatientView.read(patients);

最后,类resPatientView将具有与resPatient相同的形状,只是其预约没有患者属性,并且其医生属性被替换为没有预约属性的版本。

下面是更多的例子。1.10版本已准备就绪。将修复一些错误,并支持由spring管理配置bean。

最新更新