Spring CrudRepository - Как мне вставить запись по идентификатору внешнего ключа? - PullRequest
0 голосов
/ 08 марта 2020

При вставке записи с использованием пост-запроса ссылочная запись, связанная с внешним ключом, не связывается.

@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);

}

База данных - Таблица врача: doctor_id doctor_name кафедра 12345678 Dfirstname Dlastname ENT

POST-запрос - JSON Body {"PatientName": "Имя_первого имени_пластики", "Проблема:" Проблема с видимостью - затруднение при слабом освещении "," doctor ": {" doctorId ":" 12345678 "} }

Когда я отправляю этот запрос, столбец doctor_id таблицы пациентов не заполняется docortId.

1 Ответ

0 голосов
/ 18 марта 2020

на первый взгляд (так как сервисный слой не предоставляется) Вы должны удалить вставляемый = false и обновляемый = false из @ JoinColumn

@JoinColumn(name = "doctor_id", nullable = false, insertable = false, updatable = false)

изменить это на:

@JoinColumn(name = "doctor_id", nullable = false)

Поскольку эти директивы не позволяют jpa вставлять / обновлять столбец DOCTOR_ID

Также я предпочитаю использовать werappers вместо примитивного типа, так как @Id меняет int на Integer как предлагается здесь Использование класса Integer-обёртки или примитива int в отображении гибернации

Также кажется, что вы уже сохранили doctor (так как он уже назначил идентификатор), вы должны сначала выбрать доктора, чтобы и добавьте в него пациента с обоих концов:

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);
    }

Я не использовал геттер / сеттер, но вы должны:)

РЕДАКТИРОВАТЬ

ваш registerPatient() лог c должен выглядеть примерно так:

    @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";
    }
...