Java 如何使用JPA存储库更新实体中的一个字段
我有3个字段的实体:id、lastname和phoneNumber。我想创建一个方法,用于更新所有字段或仅更新一个或两个字段 我使用Hibernate和JPA存储库。 当我尝试更新所有字段时,一切正常,但例如,当我只想更新lastname而不更改phoneNumber时,我在输出null中使用了旧phoneNumber 以下是我从控制器获得的方法:Java 如何使用JPA存储库更新实体中的一个字段,java,spring,spring-data-jpa,Java,Spring,Spring Data Jpa,我有3个字段的实体:id、lastname和phoneNumber。我想创建一个方法,用于更新所有字段或仅更新一个或两个字段 我使用Hibernate和JPA存储库。 当我尝试更新所有字段时,一切正常,但例如,当我只想更新lastname而不更改phoneNumber时,我在输出null中使用了旧phoneNumber 以下是我从控制器获得的方法: @PutMapping("/students/update/{id}") public String updateStudentById(@Mode
@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";
}
与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 + '\'' +
'}';
}
}
@实体
@表(name=“student”)
@动态铜日期
公立班学生{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@列(name=“name”)
私有字符串名称;
@列(name=“email”)
私人字符串电子邮件;
//@OneToMany(mappedBy=“学生”)
@许多
@JoinTable(name=“course\u student”,joinColumns=@JoinColumn(name=“student\u id”),
inverseJoinColumns=@JoinColumn(name=“course\u id”))
私人名单课程;
@OneToOne(级联=级联类型.ALL)
//@JoinColumn(name=“studen/\u details\u id”)//我们有了dobule student\u details列
私人学生详情学生详情;
公开课程名单{
返回课程;
}
公共课程(列出课程){
本课程=课程;
}
公共学生详细信息getStudentDetails(){
返回学生详细信息;
}
公共无效设置StudentDetails(StudentDetails StudentDetails){
this.studentDetails=studentDetails;
}
//StudentViewController的方法
公共字符串getLastname(){
return studentDetails.getLastname();
}
公共字符串getPhoneNumber(){
return studentDetails.getPhoneNumber();
}
公立学生(){
}
公共学生(字符串名称、字符串电子邮件、StudentDetails StudentDetails){
//this.id=id;
this.name=名称;
this.email=电子邮件;
this.studentDetails=studentDetails;
}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共字符串getEmail(){
回复邮件;
}
公用电子邮件(字符串电子邮件){
this.email=电子邮件;
}
@凌驾
公共字符串toString(){
返回“学生{”+
“id=”+id+
“,name=”“+name+”\“””+
“,email='”+email+'\''+
'}';
}
}
我正在寻找解决方案,我添加了@DynamicUpdate,但它仍然不起作用。为什么不在setters中设置请求的参数呢
resultOptional.ifPresent((Student result) -> {
result.getStudentDetails().setPhoneNumber(phoneNumber);
result.getStudentDetails().setLastname(lastname);
studentRepository.save(result);
});
您忘记了在StudentDetails中设置@OneToOne映射-StudentDetails还需要类型为Student的字段,该字段将被注释为@OneToOne
此外,您还必须确保所有实体字段都已填充-请阅读有关获取类型的更多信息。您的代码工作正常。当您仅在请求中提供
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问题。
尝试使用选择和更新模式查看:嘿,我选中了它,但任何解决方案都有帮助。.我在StudentDetalis.class中添加了:@OneToOne(fetch=FetchType.EAGER)private Student;在Student.class中:@OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)private StudentDetails StudentDetails;但是没有任何帮助。非常感谢!:)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);
});