Search code examples
javajpaspring-data-jpamany-to-manycascade

Updating an entity, but without creating new records for @onetomany relationship is already exists in db table


I am searching for an answer for almost all day and couldnt figure out how to solve this. So that's why Im asking, please advise.

I got 2 entities, Patient and Dietician - both of them, stored in one table called users - I have parent entity called User and Patient/Dietician inherits from it.

What I want to do, I have a view on which Patient can update information about himself (he has to say, what age he is, height, weight, what type of diet he wants and he can choose dietician from the dropdown list (those dieticians already exists in database table) What I want to do now is that I want save Patient with those informations, but every time i do save it is saving those informations but also creating new dietician entry (duplicating it) or stating that he cannot create that dietician because emailaddress field is unique (that's how I wanted). Why every time I do save it is creating a new entry for ManyToOne relationship? Why this can't use existing Dietician, and just set FK (dietician_id) with id of existing dietician.

Here is bunch of code

@Entity
@DiscriminatorValue("1")
public class Patient extends User {
        
   private Double weight;
        
   private Double height;
        
   private Integer age;
        
   @Enumerated(value = EnumType.STRING)
   private DietType dietType;
        
   @Enumerated(value = EnumType.STRING)
   private Gender gender;
        
   @Enumerated(value = EnumType.STRING)
   private PsychicalActivity psychicalActivity;
        
   @OneToMany(mappedBy = "patient", cascade = CascadeType.ALL)
   private List<Diet> diets;
        
   @ManyToOne(cascade = CascadeType.ALL)
   private Dietician dietician;
        
   @OneToMany(mappedBy = "patient", cascade = CascadeType.ALL)
   private List<Visit> visits;  
@Entity
@DiscriminatorValue("2")
public class Dietician extends User {
        
    @OneToMany(mappedBy = "dietician", cascade = CascadeType.ALL)
    private Set<Patient> patients;
        
    @OneToMany(mappedBy = "dietician", cascade = CascadeType.ALL)
    private Set<Visit> visits;
        
    public Dietician() {}
        
    public Dietician(String firstName, String lastName, String emailAddress, String password, Set<Role> roles) {
        super(firstName, lastName, emailAddress, password, roles);
    }
@PostMapping("/update-data")
public String sendUpdateForm(@ModelAttribute Patient patientForm){
    patientService.setUserData(patientForm);
    return "patientHomePage";
}
@Override
public Patient setUserData(Patient patientForm) {
    Patient patient = patientRepository.findByEmailAddress(patientForm.getEmailAddress());
    patient.setGender(patientForm.getGender());
    patient.setPsychicalActivity(patientForm.getPsychicalActivity());
    patient.setAge(patientForm.getAge());
    patient.setDietician(patientForm.getDietician());
    
    return patientRepository.save(patient);
    }

Solution

  • When setting the dietician of a patient make sure you are using an instance loaded from the repository and not a newly created instance.

    So patient.setDietician(patientForm.getDietician()); should be changed into something like

    patient.setDietician(dieticianRepository.findById(patientForm.getDietician().getId());