Monika
Monika

Reputation: 53

How to update one field in my Entity using JPA Repository

I have Entity with 3 fields: id, lastname and phoneNumber. I want to create method which works for update all fields or only one or two.

I use Hibernate and JPA Repository. When I try to update all fields everything works well but when for example i want to update only lastname without changing of phoneNumber I have in output null insted of old phoneNumber.

Here is my method from Controller:

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

The class for update:

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

The class which has relation with StudentDetails:

@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 + '\'' +
                '}';
    }

}

I was looking for solution and I added @DynamicUpdate but still it doesn't work.

Upvotes: 5

Views: 15153

Answers (3)

Selindek
Selindek

Reputation: 3423

Your code works properly. When you only provide lastName parameter in your request, then the phoneNumber parameter will be mapped to null so you override the phoneNumer property in your entity with this null value.

Change the code in the following way:

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

Unfortunately it raises an other problem: How will you delete these fields? (How can you set them explicitly to null? )

A possible solution if you check for the "" (empty string) and set the property to null if the parameter is empty string.

It will be a quite messy code anyway...

You should consider using the Spring Data Rest package. It automatically creates all of the standard REST endpoints for your entities and handles all of these PUT/PATCH/POST/DELETE issues out of the box.

Upvotes: 2

Tom
Tom

Reputation: 224

You forget set @OneToOne mapping in StudentDetails - StudentDetails also need field of type Student which will be annotated @OneToOne.

Also you have to ensure, that all of entity fields will be filled - read more about fetch types.

Upvotes: 0

MattOverF.
MattOverF.

Reputation: 69

why don't you just set the params of your request in you setters?

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

Upvotes: 0

Related Questions