2
votes

Comment mettre à jour un champ dans mon entité à l'aide du référentiel JPA

J'ai une entité avec 3 champs: id, nom et numéro de téléphone. Je veux créer une méthode qui fonctionne pour mettre à jour tous les champs ou seulement un ou deux.

J'utilise Hibernate et JPA Repository. Quand j'essaie de mettre à jour tous les champs, tout fonctionne bien mais quand, par exemple, je veux mettre à jour uniquement le nom de famille sans changer de phoneNumber, j'ai en sortie null insted de l'ancien phoneNumber.

Voici ma méthode de Controller: p>

@Entity
@Table(name = "student")
@DynamicUpdate
public class Student {

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

    @Column(name = "name")
    private String name;
    @Column(name = "email")
    private String email;

    //@OneToMany(mappedBy = "student")
    @ManyToMany
    @JoinTable(name="course_student",joinColumns = @JoinColumn(name="student_id"),
    inverseJoinColumns = @JoinColumn(name="course_id"))

    private List<Courses> courses;

    @OneToOne(cascade = CascadeType.ALL)
   // @JoinColumn(name="studen/_details_id") // with this we have dobule student_details column
    private  StudentDetails studentDetails;


    public List<Courses> getCourses() {
        return courses;
    }

    public void setCourses(List<Courses> courses) {
        this.courses = courses;
    }

    public StudentDetails getStudentDetails() {
        return studentDetails;
    }

    public void setStudentDetails(StudentDetails studentDetails) {
        this.studentDetails = studentDetails;
    }

    // Methods for StudentViewController
    public String getLastname(){
        return studentDetails.getLastname();
    }
    public String getPhoneNumber(){
        return studentDetails.getPhoneNumber();
    }

    public Student() {
    }

    public Student(String name, String email, StudentDetails studentDetails) {
       // this.id = id;
        this.name = name;
        this.email = email;
        this.studentDetails = studentDetails;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

}

La classe pour la mise à jour:

@DynamicUpdate
@Entity
public class StudentDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name="lastname")
    private String lastname;
    @Column(name="phone_number")
    private String phoneNumber;

    public StudentDetails() {
    }

    public StudentDetails(Long id, String lastname, String phoneNumber) {
        this.id = id;
        this.lastname = lastname;
        this.phoneNumber = phoneNumber;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

La classe qui a une relation avec StudentDetails:

@PutMapping("/students/update/{id}")
public String updateStudentById(@ModelAttribute Student student, @ModelAttribute StudentDetails studentDetails,
                                String lastname, String phoneNumber,
                                @PathVariable Long id) {

    Optional<Student> resultOptional = studentRepository.findById(id); 

    //Student result =resultOptional.get();
    resultOptional.ifPresent((Student result) -> {
           result.getStudentDetails().setPhoneNumber(studentDetails.getPhoneNumber());     result.getStudentDetails().setLastname(studentDetails.getLastname());
        studentRepository.save(result);
    });
    return "Student updated";
}


3 commentaires

essayez d'utiliser le modèle de sélection et de mise à jour


Jetez un œil à: stackoverflow.com/questions/39741102/...


Hé, je l'ai vérifié, mais toutes les solutions sont utiles.


3 Réponses :


0
votes

pourquoi ne définissez-vous pas simplement les paramètres de votre requête dans vos setters?

resultOptional.ifPresent((Student result) -> {
result.getStudentDetails().setPhoneNumber(phoneNumber);
result.getStudentDetails().setLastname(lastname);
studentRepository.save(result);
});


0 commentaires

0
votes

Vous oubliez de définir le mappage @OneToOne dans StudentDetails - StudentDetails a également besoin d'un champ de type Student qui sera annoté @OneToOne.

Vous devez également vous assurer que tous les champs d'entité seront remplis - en savoir plus sur les types de récupération.


1 commentaires

J'ai ajouté dans StudentDetalis.class: @OneToOne (fetch = FetchType.EAGER) étudiant privé; et dans Student.class: @OneToOne (cascade = CascadeType.ALL, fetch = FetchType.EAGER) private StudentDetails studentDetails; mais n'aide pas du tout.



2
votes

Votre code fonctionne correctement. Lorsque vous ne fournissez que le paramètre lastName dans votre demande, le paramètre phoneNumber sera mappé à null afin que vous remplaciez le phoneNumer code> dans votre entité avec cette valeur null .

Modifiez le code de la manière suivante:

resultOptional.ifPresent((Student result) -> {
   if(studentDetails.getPhoneNumber()!=null) {
     result.getStudentDetails().setPhoneNumber(studentDetails.getPhoneNumber());     
   }
   if(studentDetails.getLastname()!=null) {
     result.getStudentDetails().setLastname(studentDetails.getLastname());
   }
   studentRepository.save(result);
});

Malheureusement, cela pose un autre problème : Comment allez-vous supprimer ces champs? (Comment pouvez-vous les définir explicitement sur null ?)

Une solution possible si vous vérifiez le "" (chaîne vide) et définissez la propriété à null si le paramètre est une chaîne vide.

Ce sera un code assez compliqué de toute façon ...

Vous devriez envisager d'utiliser le package Spring Data Rest . Il crée automatiquement tous les points de terminaison REST standard pour vos entités et gère tous ces problèmes PUT / PATCH / POST / DELETE prêts à l'emploi.


1 commentaires

Merci beaucoup ! :)