级联操作CascadeType


3个月前 219次点击 来自 后端

标签: JPA

CascadeType 定义了6种模式,其中ALL类型包括所有JPA级联类型

public enum CascadeType { 

    /** Cascade all operations */
    ALL, 

    /** Cascade persist operation */
    PERSIST, 

    /** Cascade merge operation */
    MERGE, 

    /** Cascade remove operation */
    REMOVE,

    /** Cascade refresh operation */
    REFRESH,

    /**
     * Cascade detach operation
     *
     * @since 2.0
     * 
     */   
    DETACH
}

PERSIST 级联保存

public class Student {
    @ManyToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
    private List<Course> courses = new ArrayList<>();
    //其他代码略。
}

持久化父对象时同时对子对象进行持久化,即级联保存:

Student student = new Student("s1");  
student.setCourses(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 (?, ?)

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=1
delete from course where id=1
delete from course where id=2
delete from student where id=1
  • 当没有设置级联删除时,delete主对象时,子对象只是去掉关系;remove子对象时也只是去掉关系,如果增加orphanRemoval = true则会删除remove的子对象
  • 当有设置级联删除时,delete主对象时,子对象同样会被删除

orphanRemoval

    /**
     * (Optional) Whether to apply the remove operation to entities that have
     * been removed from the relationship and to cascade the remove operation to
     * those entities.
     * @since 2.0
     */
    boolean orphanRemoval() default false;

当关联双方存在父子关系,就可以把父方的@OneToMany注解的orphanRemoval属性设为true。所谓父子关系,是指由父方来控制子方的持久化生命周期,子方对象必须和一个父方对象关联,而不允许单独存在。如果删除父方对象,应该级联删除所有关联的子方对象;如果一个子方对象不再和一个父方对象关联,应该把这个子方对象删除。

类与类之间是否存在父子关系是由业务需求决定的。通常认为客户(Customer)和订单(Order)之间存在父子关联关系,订单总是由某个客户发出的,因此一条不属于任何客户的订单是没有存在意义的。

官方文档给出的解释:

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 the orphanRemoval attribute 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. If orphanRemoval is set to true, the line item entity will be deleted when the line item is removed from the order.
The orphanRemoval attribute in @OneToMany and @oneToOne takes 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() { ... }

MERGE 级联更新/合并

当Student(父对象)中的数据改变,会相应地更新Course(子对象)中的数据。

➊
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:

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=1
update course set name=c2 where id=1
update student set name=s2 where id=1

REFRESH 级联刷新

级联刷新主要用于并发的场景下避免脏数据

假设场景 有一个订单,订单里面关联了许多商品,这个订单可以被很多人操作,
那么这个时候A对此订单和关联的商品进行了修改,与此同时,B也进行了相同的操作,
但是B先一步比A保存了数据,那么当A保存数据的时候,
就需要先刷新订单信息及关联的商品信息后,再将订单及商品保存

DETACH 级联脱管/游离

如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联。

Made with in Shangrao,China By Devler.

Copyright © Devler 2012 - 2022

赣ICP备19009883号-1

Top ↑