jpa级联(Cascade)操做

因为 重复性的操做十分烦琐,尤为是在处理多个彼此关联对象状况下,此时咱们可使用级联(Cascade)操做。级联 在关联映射中是个重要的概念,指当主动方对象执行操做时,被关联对象(被动方)是否同步执行同一操做。sql

在实际的项目中,常常可使用到级联的操做。本周也在级联上遇到了问题。数据库

级联类型

jpa的级联类型(Cascade Types)包括:app

  • ALL
  • PERSIST
  • MERGE
  • REMOVE
  • REFRESH
  • DETACH

ALL类型包括全部的jpa级联类型和Hibernate的级联类型。具体的使用方法,就是在实体的关联注解上使用级联类型:ide

@Entity  
public class Student {  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    Long id;  
  
    String name; 
    
    @OneToMany(cascade = CascadeType.ALL)
    List<Course> courseList = new ArrayList<>();  
    .......
}
  
@Entity  
public class Course {  
    @Id  
   @GeneratedValue(strategy = GenerationType.IDENTITY)  
    Long id;
    
    String name;  
    .....
}

PERSIST

PERSIST操做会将对象持久化,当使用CascadeType.PERSIST时,表明持久化父对象时,子对象也相应的持久化,也就是级联保存。code

Student student = new Student("s1");  
student.setCourseList(Arrays.asList(new Course("c1")));  
studentRepository.save(student);

对应的sql语句为:对象

insert into student (name) values (?)
insert into course (name) values (?)
insert into student_course_list (student_id, course_list_id) values (?, ?)

MERGE

MERGE操做会将具备相同标识符的对象进行更新,当时用CascadeType.MERGE时,表明当父对象更新里的子对象更新时,更新操做会传递到子对象。ip

Student student = new Student("s1");  
student.setCourseList(Arrays.asList(new Course("c1")));  
studentRepository.save(student);  

student.setName("s2");  
student.getCourseList().get(0).setName("c2");  
studentRepository.save(student);

对应的sql语句为:ci

select student0_.id as id1_1_1_, student0_.name as name2_1_1_, courselist1_.student_id as student_1_2_3_, course2_.id as course_l2_2_3_, course2_.id as id1_0_0_, course2_.name as name2_0_0_ from student student0_ left outer join student_course_list courselist1_ on student0_.id=courselist1_.student_id left outer join course course2_ on courselist1_.course_list_id=course2_.id where student0_.id=?
update course set name=? where id=?
update student set name=? where id=?

具体流程为:rem

  • 从学生表中查找学生并链接课程表
  • 更新课程中改变的属性,更新学生中改变的属性

REMOVE

REMOVE操做会删除数据库的实体,使用CascadeType.REMOVE时,会级联删除全部子对象。文档

Student student = new Student("s1");  
student.setCourseList(Arrays.asList(new Course("c1"), new Course("c2")));  
studentRepository.save(student);  
  
studentRepository.delete(student);

对应的sql语句为:

delete from student_course_list where student_id=?
delete from course where id=?
delete from course where id=?
delete from student where id=?

REFRESH

REFRESH操做表明从新从数据库中获取实体信息,使用了CascadeType.REFRESH后,会级联的获取子对象在数据库的信息。

Student student = new Student("s1");  
student.setCourseList(Arrays.asList(new Course("c1"), new Course("c2")));  
studentRepository.save(student);  
entityManager.refresh(student);

DETACH

DETACH操做表示从持久化的上下文移除对象,当使用了CascadeType.DETACH后,子对象也会从持久化的上下文中移除。

Student student = new Student("s1");  
Course course = new Course("c1");  
student.setCourseList(Arrays.asList(course));  
studentRepository.save(student);  
assertThat(entityManager.contains(student)).isTrue();  
assertThat(entityManager.contains(course)).isTrue();  
entityManager.detach(student);  
assertThat(entityManager.contains(student)).isFalse();  
assertThat(entityManager.contains(course)).isFalse();

orphanRemoval

以前的级联表明的都是从父操做到子操做的延伸,在写项目的时候,就遇到了这样的问题:学生选择了政治、英语课,而后修改学生课程为语文、数学。然而级联并不能作到当学生课程集合改变时,自动删除原先课程并建立新课程。这时候就需orphanRemoval了,官方文档给出的解释为:

When a target entity in one-to-one or one-to-many relationship is removed from the relationship, it is often desirable to cascade the remove operation to the target entity. Such target entities are considered “orphans,” and theorphanRemovalattribute can be used to specify that orphaned entities should be removed. For example, if an order has many line items and one of them is removed from the order, the removed line item is considered an orphan. IforphanRemovalis set totrue, the line item entity will be deleted when the line item is removed from the order.

TheorphanRemovalattribute in@OneToManyand@oneToOnetakes a Boolean value and is by default false.

The following example will cascade the remove operation to the orphaned customer entity when it is removed from the relationship:

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

大体就是说,当一个one-to-one或一个one-to-many的关系发生改变的时候,他会自动删除相关联的数据。

Student student = new Student("s1");  
List<Course> courses1 = new ArrayList<>();  
courses1.add(new Course("c1"));  
student.setCourseList(courses1);  
studentRepository.save(student);  
  
student.getCourseList().clear();  
student.getCourseList().add(new Course("c2"));  
studentRepository.save(student);

对应的sql语句为:

insert into course (name) values (?)
insert into student_course_list (student_id, course_list_id) values (?, ?)
delete from course where id=?

参考连接:Overview of JPA/Hibernate Cascade Types

相关文章
相关标签/搜索