【问题标题】:How to update one field in my Entity using JPA Repository如何使用 JPA 存储库更新我的实体中的一个字段
【发布时间】:2019-06-23 23:35:03
【问题描述】:

我有 3 个字段的实体:id、姓氏和电话号码。我想创建适用于更新所有字段或仅更新一两个字段的方法。

我使用 Hibernate 和 JPA 存储库。 当我尝试更新所有字段时,一切正常,但是例如,当我只想更新姓氏而不更改电话号码时,我在输出中插入了旧电话号码的空值。

这是我在 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";
}

要更新的类:

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

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

}

我正在寻找解决方案并添加了@DynamicUpdate,但它仍然不起作用。

【问题讨论】:

标签: java spring spring-data-jpa


【解决方案1】:

您的代码可以正常工作。当您在请求中仅提供 lastName 参数时,phoneNumber 参数将映射到 null,因此您使用此 null 值覆盖实体中的 phoneNumer 属性。

按以下方式更改代码:

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

不幸的是,它引发了另一个问题:您将如何删除这些字段? (如何将它们显式设置为null?)

如果您检查""(空字符串)并在参数为空字符串时将属性设置为null,则可能的解决方案。

无论如何,这将是一个相当混乱的代码......

您应该考虑使用 Spring Data Rest 包。它会自动为您的实体创建所有标准 REST 端点,并开箱即用地处理所有这些 PUT/PATCH/POST/DELETE 问题。

【讨论】:

  • 非常感谢! :)
【解决方案2】:

你为什么不在你的 setter 中设置你的请求参数?

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

【讨论】:

    【解决方案3】:

    您忘记在 StudentDetails 中设置 @OneToOne 映射 - StudentDetails 还需要 Student 类型的字段,该字段将被注释为 @OneToOne。

    您还必须确保所有实体字段都将被填充 - 阅读有关获取类型的更多信息。

    【讨论】:

    • 我在 StudentDetalis.class 中添加了:@OneToOne(fetch = FetchType.EAGER) private Student student;在 Student.class 中:@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) private StudentDetails studentDetails;但根本没有帮助。
    猜你喜欢
    • 2011-03-29
    • 1970-01-01
    • 2021-01-03
    • 2018-08-24
    • 1970-01-01
    • 2021-07-14
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多