Spring CrudRepository - 如何通过外键 ID 插入记录?
Spring CrudRepository- How do I insert a record by foreign key ID?
当使用 post 请求外键相关引用记录插入记录时未链接。
@RestController
@RequestMapping("auth")
public class PatientController {
@Autowired
private PatientService patientService;
@PostMapping(value = "patient/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public String registerPatient(@RequestBody Patient patient) {
String response = patientService.registerPatient(patient);
return "{'result':" + response + "}";
}
}
@Service
public class PatientService {
@Autowired
private PatientRepository patientRepo;
public String registerPatient(Patient patient) {
patient = patientRepo.save(patient);
}
}
@Repository
public interface PatientRepository extends CrudRepository<Patient, Integer> {
}
实体类:
@Entity
@Table(name = "patient")
public class Patient implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "patient_id")
private int patientId;
@Column(name = "patient_name", length = 200)
private String patientName;
@Column(name = "problem", length = 200)
private String problem;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
private Doctor doctor;
}
@Entity
@Table(name = "doctor")
public class Doctor implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "doctor_id")
private int doctorId;
@Column(name = "doctor_name", length = 200)
private String doctorName;
@Column(name = "department", length = 200)
private String department;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
数据库-医生Table:
doctor_id doctor_name 部门
12345678 Dfirstname Dlastname ENT
POST 请求 - JSON 正文
{
"patientName":"Pfirstname Plastname",
"problem:"能见度问题 - 弱光下的困难",
"doctor":{"doctorId":"12345678"}
}
当我发送此请求时,患者 table doctor_id 列未填充 docortId。
乍一看(因为没有提供服务层)你必须从 @JoinColumn 中删除 insertable=false 和 updatable=false
@JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
将其更改为:
@JoinColumn(name = "doctor_id", nullable = false)
因为这个指令不允许 jpa insert/update DOCTOR_ID
列
此外,我更喜欢使用 werappers 而不是原始类型,因为 @Id 将 int 更改为 Integer,如此处建议 Using wrapper Integer class or int primitive in hibernate mapping
而且你似乎已经坚持doctor
(因为它已经分配了id)你应该首先select医生到数据库并在两端添加病人:
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
这里是完整的例子:
public static void main(String[] args) {
SpringApplication.run(DemostackApplication.class, args);
}
@Component
public static class AppRunner implements ApplicationRunner {
@Autowired
MainService mainService;
@Override
public void run(ApplicationArguments args) throws Exception {
Doctor doctor = new Doctor();
doctor.department = "a";
doctor.doctorName = "Covid19 Ninja";
doctor = mainService.saveDoctor(doctor);
Patient patient = new Patient();
patient.patientName = "test";
patient.problem = "test";
patient.assignToDoctor(doctor);
Patient newPatient = mainService.savePatient(patient);
}
}
@Service
public static class MainService {
@Autowired
DoctorRepo doctorRepo;
@Autowired
PatientRepo patientRepo;
@Transactional
public Doctor saveDoctor(Doctor doctor) {
return doctorRepo.save(doctor);
}
@Transactional
public Patient savePatient(Patient patient) {
return patientRepo.save(patient);
}
}
@Entity
@Table(name = "patient")
public static class Patient implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "patient_id")
private Integer patientId;
@Column(name = "patient_name", length = 200)
private String patientName;
@Column(name = "problem", length = 200)
private String problem;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doctor_id", nullable = false)
private Doctor doctor;
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
}
@Entity
@Table(name = "doctor")
public static class Doctor implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "doctor_id")
private Integer doctorId;
@Column(name = "doctor_name", length = 200)
private String doctorName;
@Column(name = "department", length = 200)
private String department;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
我没有用过 getter/setters 但你应该:)
编辑
你的 registerPatient()
逻辑应该是这样的:
@Transactional
public String registerPatient(Patient patient) {
Integer doctorId= patinet.getDoctor().getId();
//fetch the doctor from database
Doctor doctor = doctorRepository.findById(doctorId).orElseThrow(() -> new RuntimeException("doctor not found"));
//create bidirectional reference between patient and doctor
patient.setDoctor(doctor);
doctor.getPatients().add(patient);
//save patient
patient = patientRepo.save(patient);
return "OK";
}
当使用 post 请求外键相关引用记录插入记录时未链接。
@RestController
@RequestMapping("auth")
public class PatientController {
@Autowired
private PatientService patientService;
@PostMapping(value = "patient/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public String registerPatient(@RequestBody Patient patient) {
String response = patientService.registerPatient(patient);
return "{'result':" + response + "}";
}
}
@Service
public class PatientService {
@Autowired
private PatientRepository patientRepo;
public String registerPatient(Patient patient) {
patient = patientRepo.save(patient);
}
}
@Repository
public interface PatientRepository extends CrudRepository<Patient, Integer> {
}
实体类:
@Entity
@Table(name = "patient")
public class Patient implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "patient_id")
private int patientId;
@Column(name = "patient_name", length = 200)
private String patientName;
@Column(name = "problem", length = 200)
private String problem;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
private Doctor doctor;
}
@Entity
@Table(name = "doctor")
public class Doctor implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "doctor_id")
private int doctorId;
@Column(name = "doctor_name", length = 200)
private String doctorName;
@Column(name = "department", length = 200)
private String department;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
数据库-医生Table: doctor_id doctor_name 部门 12345678 Dfirstname Dlastname ENT
POST 请求 - JSON 正文 { "patientName":"Pfirstname Plastname", "problem:"能见度问题 - 弱光下的困难", "doctor":{"doctorId":"12345678"} }
当我发送此请求时,患者 table doctor_id 列未填充 docortId。
乍一看(因为没有提供服务层)你必须从 @JoinColumn 中删除 insertable=false 和 updatable=false
@JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)
将其更改为:
@JoinColumn(name = "doctor_id", nullable = false)
因为这个指令不允许 jpa insert/update DOCTOR_ID
列
此外,我更喜欢使用 werappers 而不是原始类型,因为 @Id 将 int 更改为 Integer,如此处建议 Using wrapper Integer class or int primitive in hibernate mapping
而且你似乎已经坚持doctor
(因为它已经分配了id)你应该首先select医生到数据库并在两端添加病人:
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
这里是完整的例子:
public static void main(String[] args) {
SpringApplication.run(DemostackApplication.class, args);
}
@Component
public static class AppRunner implements ApplicationRunner {
@Autowired
MainService mainService;
@Override
public void run(ApplicationArguments args) throws Exception {
Doctor doctor = new Doctor();
doctor.department = "a";
doctor.doctorName = "Covid19 Ninja";
doctor = mainService.saveDoctor(doctor);
Patient patient = new Patient();
patient.patientName = "test";
patient.problem = "test";
patient.assignToDoctor(doctor);
Patient newPatient = mainService.savePatient(patient);
}
}
@Service
public static class MainService {
@Autowired
DoctorRepo doctorRepo;
@Autowired
PatientRepo patientRepo;
@Transactional
public Doctor saveDoctor(Doctor doctor) {
return doctorRepo.save(doctor);
}
@Transactional
public Patient savePatient(Patient patient) {
return patientRepo.save(patient);
}
}
@Entity
@Table(name = "patient")
public static class Patient implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "patient_id")
private Integer patientId;
@Column(name = "patient_name", length = 200)
private String patientName;
@Column(name = "problem", length = 200)
private String problem;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "doctor_id", nullable = false)
private Doctor doctor;
public void assignToDoctor(Doctor doctor) {
doctor.patients.add(this);
this.doctor = doctor;
}
}
@Entity
@Table(name = "doctor")
public static class Doctor implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "doctor_id")
private Integer doctorId;
@Column(name = "doctor_name", length = 200)
private String doctorName;
@Column(name = "department", length = 200)
private String department;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "doctor")
private Set<Patient> patients = new HashSet<Patient>(0);
}
我没有用过 getter/setters 但你应该:)
编辑
你的 registerPatient()
逻辑应该是这样的:
@Transactional
public String registerPatient(Patient patient) {
Integer doctorId= patinet.getDoctor().getId();
//fetch the doctor from database
Doctor doctor = doctorRepository.findById(doctorId).orElseThrow(() -> new RuntimeException("doctor not found"));
//create bidirectional reference between patient and doctor
patient.setDoctor(doctor);
doctor.getPatients().add(patient);
//save patient
patient = patientRepo.save(patient);
return "OK";
}