簡體   English   中英

更新@OneToMany 關系(Spring Boot、Spring Data)

[英]update @OneToMany relationship (Spring Boot, Spring Data)

我有一個OneToMany關系(兩個表雙向)。 當我保存醫生的專業時,它確實有效,但是當我刪除任何專業並更新醫生時,它不起作用。

醫生

@Entity
@Table(name = "doctors")
public class Doctor implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer doctorId;

    @Column(length = 20)
    private String doctorName;

    @Column(length = 9)
    private String doctorPhoneNo;

    @Column(length = 30)
    private String doctorEmailAddress;

    private String doctorProfileImage;

    @Enumerated(EnumType.STRING)
    private Status status;

    @Column(length = 6)
    private String doctorCmp;

    @OneToMany(mappedBy = "doctor", cascade = CascadeType.ALL)
//  @JsonIgnore
    private Set<DoctorSpecialties> doctorSpecialties;

    public Doctor() {
        this.doctorSpecialties = new HashSet<>();
    }

    public Doctor(Integer id){
        this();
        this.doctorId = id;
    }

    // getters y setters
}

專業

@Entity
@Table(name = "specialties")
public class Specialty implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer specialtyId;

    private String specialtyName;

    @OneToMany(mappedBy = "specialty")
    @JsonIgnore
    private Set<DoctorSpecialties> doctorSpecialties;

    public Specialty() {
    }

    public Specialty(Integer id) {
        this.specialtyId = id;
    }

    // getters and setters
  }

醫生專長

@Entity
@Table(name = "doctor_specialties")
public class DoctorSpecialties implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "doctor_id")
    private Doctor doctor;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "specialty_id")
    private Specialty specialty;

    @OneToMany
    @JoinColumn(name = "doctor_specialties_id")
    private Set<Appointment> appointments;

    @OneToMany
    @JoinColumn(name = "doctor_specialties_id")
    private Set<DoctorSchedule> schedules;

    public DoctorSpecialties(){

    }

    public DoctorSpecialties(Specialty specialty, Doctor doctor){
        this.specialty = specialty;
        this.doctor = doctor;
    }
      getters / setters
 }

控制器

@PostMapping(value = "/saveSpecialties/{id}")
public String saveDoctorSpecialties(@RequestParam(required = false) String[] specialtiesId,
                                    @PathVariable Integer id, RedirectAttributes message) {

    if (id != null && id > 0) {
        Doctor doctor = doctorService.findOne(id);

        if (doctor != null) {

            // It does not work
            doctor.getDoctorSpecialties().forEach(ds -> doctorSpecialtiesService.delete(ds.getId()));

            doctor.getDoctorSpecialties().clear();

            if (specialtiesId != null) {
                for (String specialtyId : specialtiesId) {
                    DoctorSpecialties ds = new DoctorSpecialties();
                    ds.setSpecialty(new Specialty(Integer.parseInt(specialtyId)));
                       
                    ds.setDoctor(doctor);

                    doctor.getDoctorSpecialties()
                            .add(ds);
                }
                
            }
            doctorService.update(doctor);
            message.addFlashAttribute("success", "Specialties successfully saved.");
            return "redirect:/doctors/profile/{id}/specialties";
        }
    }
    // specialtiesId = new String[]{};
    message.addFlashAttribute("error", "Doctor doesn't exists");
    return "redirect:/doctors/list";
}

安慰:

2021-10-30 21:19:13.330 DEBUG 44504 --- [nio-8080-exec-7] org.hibernate.SQL :選擇doctor0_.doctor_id 作為doctor_i1_3_0_,doctor0_.doctor_cmp 作為doctor_c2_3_0_doctor_c2_3_0_addressdoctor_c2_3_0_doctor_c2_3_0_0 .doctor_name 作為doctor_n4_3_0_,doctor0_.doctor_phone_no 作為doctor_p5_3_0_,doctor0_.doctor_profile_image 作為doctor_p6_3_0_,doctor0_.status 作為status7_3_0_ 從醫生doctor0_ 那里doctor0_.doctor_id=? 2021-10-30 21:19:13.339 DEBUG 44504 --- [nio-8080-exec-7] org.hibernate.SQL:選擇doctorspec0_.doctor_id作為doctor_i2_2_0_,doctorspec0_.id作為id1_2_1.id_doctor_id_doctor_id_doctor_id_doctor_id_doctor_id .doctor_id 作為doctor_i2_2_1_,doctorspec0_.specialty_id 作為specialt3_2_1_ 來自doctor_specialties doctorspec0_ where doctorspec0_.doctor_id=? 2021-10-30 21:19:13.401 DEBUG 44504 --- [nio-8080-exec-8] org.hibernate.SQL:選擇doctor0_.doctor_id作為doctor_i1_3_0_,doctor0_.doctor_cmp作為doctor_c2_3_0_addressdoctor_c2_3_0_doctor_c2_3_0_doctor_c2_3_0_0 .doctor_name 作為doctor_n4_3_0_,doctor0_.doctor_phone_no 作為doctor_p5_3_0_,doctor0_.doctor_profile_image 作為doctor_p6_3_0_,doctor0_.status 作為status7_3_0_ 從醫生doctor0_ 那里doctor0_.doctor_id=? 2021-10-30 21:19:13.404 DEBUG 44504 --- [nio-8080-exec-8] org.hibernate.SQL :選擇 specialt0_.specialty_id 作為 specialt1_7_0_,doctorspec1_.id 作為 id1_2_1_doctor,doctor_i_doctor1_doctor_1_doctor_i_23. .specialty_name如specialt2_7_0_,doctorspec1_.doctor_id如doctor_i2_2_1_,doctorspec1_.specialty_id如specialt3_2_1_,doctorspec1_.specialty_id如specialt3_2_0__,doctorspec1_.id如id1_2_0__,doctor2_.doctor_cmp如doctor_c2_3_2_,doctor2_.doctor_email_address如doctor_e3_3_2_,doctor2_.doctor_name如doctor_n4_3_2_,doctor2_.doctor_phone_no作為doctor_p5_3_2_,doctor2_.doctor_profile_image asdoctor_p6_3_2_,doctor2_.status as status7_3_2_ from specialties special0_內連接doctor_specialties doctorspec1_ on special0_.specialty_id=doctorspec1_.specialty_id 內連接doctor2_ ondoctorspec1_.ctor_do=doctor_id 2021-10-30 21:19:13.565 DEBUG 44504 --- [nio-8080-exec-4] org.hibernate.SQL :選擇 specialt0_.specialty_id 作為 specialt1_7_0_,doctorspec1_.id 作為 id1_2_1_,doctor_i_doctor,doctor_i_23_doctor .specialty_name如specialt2_7_0_,doctorspec1_.doctor_id如doctor_i2_2_1_,doctorspec1_.specialty_id如specialt3_2_1_,doctorspec1_.specialty_id如specialt3_2_0__,doctorspec1_.id如id1_2_0__,doctor2_.doctor_cmp如doctor_c2_3_2_,doctor2_.doctor_email_address如doctor_e3_3_2_,doctor2_.doctor_name如doctor_n4_3_2_,doctor2_.doctor_phone_no作為doctor_p5_3_2_,doctor2_.doctor_profile_image asdoctor_p6_3_2_,doctor2_.status as status7_3_2_ from specialties special0_內連接doctor_specialties doctorspec1_ on special0_.specialty_id=doctorspec1_.specialty_id 內連接doctor2_ ondoctorspec1_.ctor_do=doctor_id

沒有刪除語句...

------------------------ 編輯 1 ------------------------

Doctor find = doctorRepository.findById(1).get();
    
DoctorSpecialties ds1 = new DoctorSpecialties();
ds1.setSpecialty(specialtyRepository.findById(1).get());
ds1.setDoctor(find);
    
DoctorSpecialties ds2 = new DoctorSpecialties();
ds2.setSpecialty(specialtyRepository.findById(2).get());
ds2.setDoctor(find);
    
find.getDoctorSpecialties().add(ds1);
find.getDoctorSpecialties().add(ds2);

doctorRepository.save(find);

我做了一些測試,我不能完全理解。 我做了,它只在我實際添加兩個對象時保存一次。

insert into doctor_specialties (id, doctor_id, specialty_id) values (null, ?, ?)

------------------------ 編輯 2 ------------------------

DoctorSpecialties (修改構造函數)

@Entity
@Table(name = "doctor_specialties")
public class DoctorSpecialties implements Serializable {

    public DoctorSpecialties(Integer specialtyId, Doctor doctor) {
        this.specialty = new Specialty(specialtyId);
        this.doctor = doctor;
    }

 }

控制器

@PostMapping(value = "/saveSpecialties/{id}")
public String saveDoctorSpecialties(@RequestParam(required = false) String[] specialtiesId,
                                    @PathVariable Integer id, RedirectAttributes message) {
    if (id != null && id > 0) {

        doctorService.saveDelete(id);

        Doctor doctor = doctorService.findOne(id);
        if (specialtiesId != null && specialtiesId.length > 0) {
            for(String idSpecialty : specialtiesId){
                doctorSpecialtiesService.save(new DoctorSpecialties(Integer.parseInt(idSpecialty), doctor));
            }
        }
        message.addFlashAttribute("success", "Specialties successfully saved.");
        return "redirect:/doctors/profile/{id}/specialties";
    }
    message.addFlashAttribute("error", "Doctor doesn't exists");
    return "redirect:/doctors/list";
}

服務

@Override
@Transactional
public void saveDelete(Integer doctorId) {
    Doctor doctor = this.doctorRepository
            .findById(doctorId).get();
    doctor.getDoctorSpecialties().clear();
}

安慰:

選擇doctor0_.doctor_id如doctor_i1_3_0_,從醫生doctor0_ doctor0_.doctor_cmp如doctor_c2_3_0_,doctor0_.doctor_email_address如doctor_e3_3_0_,doctor0_.doctor_name如doctor_n4_3_0_,doctor0_.doctor_phone_no如doctor_p5_3_0_,doctor0_.doctor_profile_image如doctor_p6_3_0_,doctor0_.status如status7_3_0_其中doctor0_.doctor_id = ? 選擇doctorspec0_.doctor_id作為doctor_i2_2_0_,doctorspec0_.id作為id1_2_0_,doctorspec0_.id作為id1_2_1_,doctorspec0_.doctor_id作為doctor_i2_2_1_,doctorspec0_.specialty_id作為specialt3_2_1_來自doctor_specialties_doctorspec_doctor_specialties_doctor_spec

更新預約 set doctor_specialties_id=null where doctor_specialties_id=?

更新doctor_schedules 設置doctor_specialties_id=null 哪里doctor_specialties_id=?

從doctor_specialties 中刪除id=?

任何一方已mappedBy為擁有方。

這意味着類似於:“關系這一側的修改已經映射到關系的另一側,因此無需在額外的表中單獨跟蹤它。”

檢查此 url 以獲取更多信息ORM 映射中的“擁有方”是什么?

對於事務中的一對多關系,一旦您獲得父級 ( Doctor ) 並遍歷其子級 ( DoctorSpecialties ) [換句話說,一旦您將整個父級及其子級加載到 Persistent 狀態],您將不會能夠通過其repository直接刪除您的DoctorSpecialties


您可以嘗試類似下面的示例來查看它:

@Transactional
public void removeLine(Long doctorId, Long specId) {
    Doctor doctor = this.doctorRepository  // (1)
        .findById(doctorId)
        .orElseThrow(IllegalArgumentException::new);
    this.doctorSpecialtiesRepository.deleteById(specId); // (2)
}

在(1)中,我們將doctor加載到持久狀態。 所以在這里,如果fetch = FetchType.EAGER ,這意味着它將把doctor和它所有的doctor doctorSpecialties到持久狀態,這個原因 (2) 不會給你任何影響。

否則,如果fetch = FetchType.LAZY ,它只加載doctor到持久狀態,並且在(2)它將被成功地刪除。

你的情況很相似,雖然fetch = FetchType.LAZY ,但你使用forEach循環了孩子,並將doctorSpecialties加載到持久狀態。 這就是您無法刪除它們的原因。


建議:在您的父實體中使用orphanRemoval = true

@OneToMany(mappedBy = "doctor", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<DoctorSpecialties> dss;

只需在您的方法中清除其子項(在@Transactional 方法中)

doctor.getDoctorSpecialties().clear();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM