11、级联映射-级联持久化、更新和删除

1、什么是级联映射?

对于一对多或者多对一、多对多等关系对象时,当保存某个一对象时,与这个依赖的对象都应该自动保存或更新。就是保存瞬时状态的主对象时,同时将关联的对象也一起保存。

比如:部门和员工表,一对多关系,当保存部门数据时,和部门有关联的员工表也同时保存,之前我们都说各自调用persist()方法,都保存一遍。我们可不可以当保存部门或员工表时,把对应的员工或部门信息也同时保存?

2、级联映射类型

  1. cascade = CascadeType.PERSIST
    保存主对象时,将关联的对象持久化到数据库中
  2. cascade = CascadeType.REFRESH
    查询主对象的同时,重新查询关联的对象
  3. cascade = CascadeType.REMOVE
    删除主对象的同时,删除关联的对象
  4. cascade = CascadeType.DETACH
    主对象变为游离状态时,把关联的对象也转变为游离状态
  5. cascade = CascadeType.MERGE
    更新主对象的同时,更新关联对象
  6. cascade = CascadeType.ALL
    以上所有的级联关系简写

3、级联关系使用案例

3.1、类型定义

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "department_id")
    private List<Employee> employees;
}

@Data
@Entity
public class Employee {
    @Id
    @GeneratedValue
    private long id;
    private String name;
}

3.2、persistence.xml配置

<class>com.hongying.entity.one2many.Department</class>
        <class>com.hongying.entity.one2many.Employee</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>

3.3、默认配置时,保存-必须独自调用persist

@Test
    public void save(){
        Department d1=new Department();
        d1.setName("IT开发部");

        Employee gg=new Employee();
        gg.setName("gg");
        Employee jake=new Employee();
        jake.setName("jake");

        List<Employee> users=new ArrayList<>();
        users.add(gg);
        users.add(jake);
        d1.setEmployees(users);

        //保存
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        //当没有设置级联保存时,每个对象都必须独自调用persist()方法进行数据持久化
        entityManager.persist(d1);
        entityManager.persist(gg);
        entityManager.persist(jake);

        entityManager.getTransaction().commit();
        entityManager.close();

    }

3.4、只保存 entityManager.persist(d1) 时报错

有关联对象未保存,异常:
object references an unsaved transient instance - save the transient instance before flushing

 entityManager.persist(d1);
//entityManager.persist(gg);
//entityManager.persist(jake);

4、级联映射使用

4.1、CascadeType.PERSIST

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "department_id")
    private List<Employee> employees;
}

此时只保存entityManager.persist(d1)时,可以把关联对象同时保存:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: update Employee set department_id=? where id=?
Hibernate: update Employee set department_id=? where id=?

在这里插入图片描述

4.2、CascadeType.REMOVE 级联删除

@Before
    public void save(){
        Department d1=new Department();
        d1.setName("IT开发部");

        Employee gg=new Employee();
        gg.setName("gg");
        Employee jake=new Employee();
        jake.setName("jake");

        List<Employee> users=new ArrayList<>();
        users.add(gg);
        users.add(jake);
        d1.setEmployees(users);

        //保存
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        //当没有设置级联保存时,每个对象都必须独自调用persist()方法进行数据持久化
        entityManager.persist(d1);
//        entityManager.persist(gg);
//        entityManager.persist(jake);

        entityManager.getTransaction().commit();
        entityManager.close();

    }

    @Test
    public void delete(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        //删除部门时查看是否会级联员工都会删除
        Department department = entityManager.find(Department.class, 1L);
        entityManager.remove(department);

        entityManager.getTransaction().commit();
        entityManager.close();
    }

当未配置级联删除CascadeType.REMOVE时,删除部门时,只会把关系和部门信息删除。员工信息并没有删除

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: update Employee set department_id=? where id=?
Hibernate: update Employee set department_id=? where id=?
Hibernate: select department0_.id as id1_0_0_, department0_.name as name2_0_0_ from Department department0_ where department0_.id=?
Hibernate: update Employee set department_id=null where department_id=?
Hibernate: delete from Department where id=?

4.2.2、配置级联删除 CascadeType.REMOVE

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @OneToMany(cascade = {
            CascadeType.PERSIST,CascadeType.REMOVE
    })
    @JoinColumn(name = "department_id")
    private List<Employee> employees;
}

当配置级联删除CascadeType.REMOVE 时,删除部门信息时,会级联把当前部门下的员工信息一同删除。

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: update Employee set department_id=? where id=?
Hibernate: update Employee set department_id=? where id=?
Hibernate: select department0_.id as id1_0_0_, department0_.name as name2_0_0_ from Department department0_ where department0_.id=?
Hibernate: select employees0_.department_id as departme3_0_1_, employees0_.id as id1_1_1_, employees0_.id as id1_1_0_, employees0_.name as name2_1_0_ from Employee employees0_ where employees0_.department_id=?

Hibernate: update Employee set department_id=null where department_id=?
Hibernate: delete from Employee where id=?
Hibernate: delete from Employee where id=?
Hibernate: delete from Department where id=?

4.3、级联更新 CascadeType.MERGE

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    //cascade 设置级联映射关系。orphanRemoval 级联删除时要不要把关联数据一同删除?默认只删除关系数据
    @OneToMany(cascade = {
            CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.MERGE
    },orphanRemoval = true)
//    @OneToMany(cascade =CascadeType.ALL,orphanRemoval = true)
    @JoinColumn(name = "department_id")
    private List<Employee> employees;
}


@Before
    public void save(){
        Department d1=new Department();
        d1.setName("IT开发部");

        Employee gg=new Employee();
        gg.setName("gg");
        Employee jake=new Employee();
        jake.setName("jake");

        List<Employee> users=new ArrayList<>();
        users.add(gg);
        users.add(jake);
        d1.setEmployees(users);

        //保存
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        //只保存主对象即可
        entityManager.persist(d1);

        entityManager.getTransaction().commit();
        entityManager.close();

    }

@Test
    public void update(){
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();
        Department department = entityManager.find(Department.class, 1L);

        //1、添加新员工
        Employee e1=new Employee();
        e1.setName("new e1");
        department.getEmployees().add(e1);

        //2、修改员工信息
        //update Employee set name=? where id=?
        department.getEmployees().get(1).setName("update name");

        //3、删除员工
        //3.1、删除数据时,只会把关系删除,不会把子表-员工记录删除
        //update Employee set department_id=null where department_id=? and id=?
        //3.2、可设置 orphanRemoval=true,把级联数据也同时删除
        //delete from Employee where id=?
        department.getEmployees().remove(0);

        //级联操作,即使不写merge()保存方法,在提交事务时,会级联更新
//        entityManager.merge(department);

        entityManager.getTransaction().commit();
        entityManager.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值