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

相關文章
相關標籤/搜索