2017-09-28 45 views
0

上下文更新与各协会

我有两个@OneToMany@ManyToMany关联的实体的部分设置实体。我从前端收到一个对象,其中只设置了一些属性(而不是关联)。目标是更新数据库中该实体的数据。

问题

接收的对象是一个分离的实体,所以当它的更新,合并操作被调用。由于没有设置关联,@ManyToMany部分被删除,但不是@OneToMany(因为没有级联)。一种选择是从数据库中检索实体,加载@ManyToMany关联,然后将所有属性从前端对象复制到该实体,然后合并,坚持对象,但我不确定这是否是最佳做法。

代码

在数据库中创建一个完整的对象

Course hibernate = new Course(); 
    hibernate.setName("Hibernate"); 
    Course java = new Course(); 
    java.setName("Java"); 
    entityManager.persist(hibernate); 
    entityManager.persist(java); 
    Address address = new Address(); 
    address.setName("White House"); 
    entityManager.persist(address); 
    Student student = new Student(); 
    student.setName("Sydney"); 
    student.addAddress(address); 
    student.addCourse(hibernate); 
    student.addCourse(java); 
    entityManager.persistAndFlush(student); 
    entityManager.clear(); 

    Hibernate: call next value for hibernate_sequence 
    Hibernate: call next value for hibernate_sequence 
    Hibernate: call next value for hibernate_sequence 
    Hibernate: call next value for hibernate_sequence 
    Hibernate: insert into course (name, id) values (?, ?) 
    Hibernate: insert into course (name, id) values (?, ?) 
    Hibernate: insert into address (name, student_id, id) values (?, ?, ?) 
    Hibernate: insert into student (name, id) values (?, ?) 
    Hibernate: update address set name=?, student_id=? where id=? 
    Hibernate: insert into student_course (students_id, courses_id) values (?, ?) 
    Hibernate: insert into student_course (students_id, courses_id) values (?, ?) 

从前端

Student partialStudent = new Student(); 
    partialStudent.setId(student.getId()); 
    partialStudent.setName("Sydney Updated"); 
    Student attachedPartialStudent = entityManager.merge(partialStudent); 
    entityManager.persistAndFlush(attachedPartialStudent); 
    entityManager.clear(); 

这部分坚持的对象生成一个DELETE SQL

Hibernate: select student0_.id as id1_41_0_, student0_.name as name2_41_0_ from student student0_ where student0_.id=? 
    Hibernate: select courses0_.students_id as students1_42_0_, courses0_.courses_id as courses_2_42_0_, course1_.id as id1_13_1_, course1_.name as name2_13_1_ from student_course courses0_ inner join course course1_ on courses0_.courses_id=course1_.id where courses0_.students_id=? 
    Hibernate: update student set name=? where id=? 
    Hibernate: delete from student_course where students_id=? 

学生实体:

@Entity 
public class Student { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") 
    @SequenceGenerator(name = "sequenceGenerator") 
    private Long id; 

    @NotNull 
    @Column(name = "name", nullable = false) 
    private String name; 

    @OneToMany(mappedBy = "student") 
    private Set<Address> addresses = new HashSet<>(); 

    @ManyToMany 
    @JoinTable(name = "student_course") 
    private Set<Course> courses = new HashSet<>(); 

    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 Set<Course> getCourses() { 
     return courses; 
    } 

    public void setCourses(Set<Course> courses) { 
     this.courses = courses; 
    } 

    public void addCourse(Course course) { 
     courses.add(course); 
     course.getStudents().add(this); 
    } 

    public void removeCourse(Course course) { 
     courses.remove(course); 
     course.getStudents().remove(this); 
    } 

    public Set<Address> getAddresses() { 
     return addresses; 
    } 

    public void setAddresses(Set<Address> addresses) { 
     this.addresses = addresses; 
    } 

    public void addAddress(Address address) { 
     addresses.add(address); 
     address.setStudent(this); 
    } 

    public void removeAddress(Address address) { 
     addresses.remove(address); 
     address.setStudent(null); 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof Student)) return false; 
     Student student = (Student) o; 
     return Objects.equals(id, student.id); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(id); 
    } 
} 

课程实体:

@Entity 
public class Course { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") 
    @SequenceGenerator(name = "sequenceGenerator") 
    private Long id; 

    @NotNull 
    @Column(name = "name", nullable = false) 
    private String name; 

    @ManyToMany(mappedBy = "courses") 
    private Set<Student> students = new HashSet<>(); 

    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 Set<Student> getStudents() { 
     return students; 
    } 

    public void setStudents(Set<Student> students) { 
     this.students = students; 
    } 

    public void addStudent(Student student) { 
     students.add(student); 
     student.getCourses().add(this); 
    } 

    public void removeStudent(Student student) { 
     students.remove(student); 
     student.getCourses().remove(this); 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof Course)) return false; 
     Course course = (Course) o; 
     return Objects.equals(id, course.id); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(id); 
    } 
} 

地址实体:

@Entity 
public class Address { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") 
    @SequenceGenerator(name = "sequenceGenerator") 
    private Long id; 

    @NotNull 
    @Column(name = "name", nullable = false) 
    private String name; 

    @ManyToOne 
    private Student student; 

    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 Student getStudent() { 
     return student; 
    } 

    public void setStudent(Student student) { 
     this.student = student; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof Address)) return false; 
     Address address = (Address) o; 
     return Objects.equals(id, address.id); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(id); 
    } 
} 

回答

0

接收的对象是分离的实体,所以当它的更新,合并操作被调用。由于没有设置关联,所以@ ManyToMany部分被删除,但不是@OneToMany(因为没有级联)。

当你有一个分离的实体,正常使用的情况是,你把它传递到一些变化的实体做出的前端。当这个修改后的实体实例从前端返回并调用entitymanager.merge()操作时,它不应删除数据库中的关联。

您所描述的情况,即协会被删除(不管级联的设置与否)如果您的关联设置为null

student.setCourses(null); 

只能发生,或者如果你创建了一个新的Student的实例,例如studentNew,复制了原始分离实例的一些字段,并将studentNew传递给了终端。在这种情况下,当从前端收到studentNew时,courses属性为null。如果发生这种情况,你有两个选择:

  • ,如果你有旧脱管的实例

    各地复制回的studentNew它的状态,并合并该实例。

  • 否则,您必须使用ID从数据库加载实体,并将更改后的状态复制到受管实例。