首页 > 解决方案 > 多个嵌套实体上的 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;

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

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

标签: springspring-boothibernatespring-data-jpaspring-data

解决方案


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

// 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管理的configure bean。


推荐阅读