我有3个字段的实体:id,姓氏和phoneNumber。我想创建一种适用于更新所有字段或仅更新一两个字段的方法。
我使用Hibernate和JPA存储库。 当我尝试更新所有字段时,一切正常,但是例如,当我只想更新姓氏而不更改phoneNumber时,我在输出null时会插入旧的phoneNumber。
这是我来自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,但仍然无法正常工作。
答案 0 :(得分:0)
为什么不只是在设置器中设置请求的参数?
resultOptional.ifPresent((Student result) -> {
result.getStudentDetails().setPhoneNumber(phoneNumber);
result.getStudentDetails().setLastname(lastname);
studentRepository.save(result);
});
答案 1 :(得分:0)
您忘记了StudentDetails中设置的@OneToOne映射-StudentDetails还需要类型为Student的字段,该字段将被注释为@OneToOne。
还必须确保所有实体字段都将被填充-了解有关提取类型的更多信息。
答案 2 :(得分:0)
您的代码正常工作。当您仅在请求中提供lastName
参数时,phoneNumber
参数将映射到null
,因此您可以使用此{{1}覆盖实体中的phoneNumer
属性}值。
通过以下方式更改代码:
null
不幸的是,这引起了另一个问题:如何删除这些字段? (如何将它们显式设置为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
(空字符串)并将属性设置为""
(如果参数为空字符串),则可能是一种解决方案。
反正这将是一个非常混乱的代码...
您应该考虑使用Spring Data Rest软件包。它会自动为您的实体创建所有标准REST端点,并开箱即用地处理所有这些PUT / PATCH / POST / DELETE问题。