`

【JPA 级联保存/级联删除】@OneToMany (双向) 一对多--整个世界都干净了以及无法级联删除因为外键关联

    博客分类:
  • JPA
 
阅读更多

http://blog.sina.com.cn/s/blog_6826662b01016ylz.html

 看过前两篇帮助文档 【JPA】 @OneToOne 单向 和 【JPA】@OneToOne 双向 想必大家对级联操作已经充满了好奇和期待吧。那么本文将会想大家介绍JPA的级联保存操作。在此之前,我希望你能先看下这篇文档,对级联注释的各个属性有一个大概的了解。传送门:【JPA】 级联标签的解释 @Cascade
      在生活中,有许多关系都是一对多的。School(学校)和 Studnet(学生)之间的关系就是典型的一对多关系。一所学校,有多名学生。但是一个学生,只能属于一所学校。在这里,我们将这个关系设置为一个双向的关系。也就说,通过学生实体,我们可以得到他就读的学校的实体。同样,通过一个学校实体,我们也可一得到在这所学校就读的学生实体的集合。


--------< 例 子 >----------------------------------------------------------------------------------------------------------


//学生Model ,这个双向一对多关系的维护端。一般来说,在双向一对多关系中,"多"这一端,一般都是关系的维护端。
@Entity
@Table(name = "student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    //在表中建立外键 "school_fk"
    
    @ManyToOne
    @JoinColumn(name="school_fk")
    private School school;
   
//省略若干get / set
}




@Entity
@Table(name = "school")
public class School {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    @OneToMany(mappedBy="shcool")
    //设置 :级联 保存/新建 操作 。新建 学校和学生的时候,保存新建的学校那么新建的学生也同时被保存
    @Column(cascade={CascadeType.PERSIST})
    private List students;


    //手动构造添加学生的方法
    public void addStudent(Strudent stu){
            if(stu != null){
                 students.add(stu);
            }
    }


//省略若干get / set
}
-----------------------------------------------------< 测试方法 >--------------------------------------------------------------
public class Test(){


    public void testCreate(){
         School school = new School();
         school.setName("学校");


         Student st1 = new Student();
         st1.setName("学弟");
         st1.setSchool(school);
         studnetDAO.save(st1);
       
         Student st2 = new Student();
         st2.setName("学长");
         st2.setSchool(school);
         studnetDAO.save(st2);


         //添加学生
         school.addStudent(st1);
         school.addStudent(st2);
         schoolDAO.save(school);
        //以上的保存方法并不是级联保存操作。我们在学校实体上设置了,级联保存操作。
        //我们希望JPA这样做,在新建学校,新建多名学生时。只要将学生的所属学校设置完成后,保存学校,即可保存所属该校的学生。
    }


    //级联保存,测试方法
    public void testPersistCreateSchool(){
            //级联保存演示:已经在学校(School)Model 中添加了 级联保存操作:cascade={CascadeType.PERSIST}
       
         School school = new School();
         school.setName("学校");


         Student st1 = new Student();
         st1.setName("学弟");
         st1.setSchool(school);
         //  不需要显示保存学生 st1
         //studnetDAO.save(st1); 
       
         Student st2 = new Student();
         st2.setName("学长");
         st2.setSchool(school);
         //  不需要显示保存学生 st2
         //studnetDAO.save(st2);


         //添加学生
         school.addStudent(st1);
         school.addStudent(st2);
         schoolDAO.save(school);// 保存学校,学校内新建的学生也[st1、st2]被保存了。(级联保存)
    }


    //测试删除
    public void testDeleteSchool(){
            //革命第一步,创建学校。
            testCreate();
            schoolDAO.delete(school);//后台报错
            //avax.persistence.RollbackException: Error while commiting the transaction Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint...
              
             //之前我们已经知道,想要删除关系的被维护端,必须先从维护端解除关系。才能正常删除。所以我们要做的就是,先从学生端,解除关系。
    
        List<Strudnet> students = school.getStudentList();
        for(int i=0;i<students.size();i++){
                Student stu = students.get(i);
                stu.setSchool(null);//手动从学生实体解除挂系
        }
        schoolDAO.delete(school);//现在,学校被正常的删除了。该校的两名学生信息依然保存在数据库中。只是,他们没有所属学校了。


        //看到这里,你一定会责备我。JPA不是很强大么?不是很灵活多变么?不是很神奇么?
        //为什么删除一个实体,还需要循环解除关系,这么繁琐的操作?!
        //其实,我们有方法可以直接删除学校。并且,不需要进行这种循环从学生实体解除关系的操作。但是,相信我,这种方法你可能不会接受。下面,就让我们来看看JPA的级联删除。
        //修改学校的Model 中,在校生字段()的注释:@Column(cascade={CascadeType.PERSIST})
        //改为:@Column(cascade={CascadeType.PERSIST,CascadeType.REMOVE}) 添加级联删除操作。那么,现在你就可以直接调用删除学校的方法了。
        schoolDAO.delete(school);//现在,学校也被正常删除了。但是,接下来的一幕,你可能不愿意看到。
        Stduent stu = studentDAO.findByName(学长");
        //打印的结果为: null   是的,你没看错。该校所有的学生也被级联删除了...
        //此时,你应该对JPA的级联删除有所理解了。它删除的对象是实体。级联指的是级联实体。如果,在学生的Model 中添加了一个级联删除的操作,那么删除一个学生,那这个学生所属的学校也会被删除掉。
        //所以,在这里,我要提醒你。级联的删除操作要慎用。因为,他的破坏性太大了。级联删除的操作,并不是针对某个字段,而是它所管理的实体。
}
       
        //测试删除
        public void testDeleteStudent(){
        //创建学校和学生
        testCreate();
        studentDAO.delete(st1);//此时,st1(创建时,名字叫“学弟”的学生)已经被从数据库中删除了。但是,他所属的学校并没受影响。只不过,st1已经从学校的 学生集合里删除了。这都是由JPA来完成的。


        //现在,我们假设:我们没有执行刚才那部。st1没有被删除。学校依然拥有两名学生。
        //在,Stuent的Model 中添加级联删除的操作。@JoinColumn(name="school_fk",cascade={CascadeType.REMOVE})   并且,School 的 Model中也添加级联删除的操作。
        //此时,数据库中,只有一所学校和两名学生的信息。
        studentDAO.delete(st1);
        //哇,全世界都干净了。如果这个时候查看数据库。你会发现,所有的数据都没了。为什么会这样呢?
        //让我们来看看JPA都干了什么:
        1:删除 st1
        2:school 被 st1 级联删除
        3:st2 被 school 级联删除
        //所以,你才会发现,数据库中所有的信息都消失了。当然,如果之前,数据库中还有别的学校和别的学校所属学生。那么它们的信息是不受影响的。
       //罗嗦了这么多,我感到很抱歉。我只是想提醒你,一定要慎用这个级联的删除操作。千万不用在建立Model 的时候,顺手添加一个级联保存删除之类的操作。一定要根据自己的需求。和操作的实际效果,仔细斟酌之后,再付诸于行动。否则,你直接来个CascadeType.ALL 大多数情况下,它带给你的都是痛苦的回忆。


       }
//省略main 方法
}


分享到:
评论

相关推荐

    10_JPA详解_JPA中的一对多双向关联与级联操作.zip

    本资料包"10_JPA详解_JPA中的一对多双向关联与级联操作.zip"聚焦于JPA中的一个重要概念——一对多双向关联及其级联操作。以下是对这一主题的详细阐述。 **一对多关联** 在关系数据库设计中,一对多关联是最常见的...

    JPA中的一对多双向关联与级联操作

    本篇将深入探讨JPA中的一对多双向关联及其级联操作,这对于理解和高效使用JPA进行数据操作至关重要。 一对多关联是数据库设计中的常见关系类型,一个实体可以拥有多个相关联的实体实例。在JPA中,这种关系可以通过...

    Hibernate 一对多、多对一、级联、加载、反转

    在Java持久化框架Hibernate中,一对多(One-to-Many)、多对一(Many-to-One)、级联(Cascading)、加载(Loading)和反转(Inversing)是关系映射的重要概念,它们对于理解如何在数据库和对象之间有效地管理关联至...

    jpa--11.双向一多

    **JPA 双向一对多关系详解** 在Java Persistence API(JPA)中,数据建模是通过实体类和它们之间的关联来实现的。在实际的业务场景中,经常会出现两个实体之间存在一对多(One-to-Many)的关系,比如一个用户可以有...

    JPA学习总结(三)--JPAOneToMany双向关联

    在本篇《JPA学习总结(三)--JPAOneToMany双向关联》中,我们将深入探讨Java Persistence API (JPA)中的OneToMany关系映射,这是一种在数据库表之间建立一对多关联的方式。JPA作为ORM(对象关系映射)框架,允许我们...

    JPA_OneToMany学习教程

    1. **OneToMany关系**:在关系数据库中,一对一、一对多和多对多是最常见的关系类型。OneToMany关系表示一个实体(父实体)可以与多个其他实体(子实体)相关联。例如,一个用户可能有多个订单,这就是典型的一对多...

    hibernate一对多,多对一,一对多双向关联

    在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户(多对一),而一个商品可以被多个订单购买,同时一个订单也可以包含多个商品(一对多双向关联)。这个标题暗示...

    jpa--10.单向一对多

    在Java Persistence API (JPA) 中,"单向一对多"是一种常见的关系映射类型,它代表了数据库中两个实体间的一种关联。这种关联意味着一个实体(“一方”)可以与多个其他实体(“多方”)相关联,而反过来,多方并不...

    spring jpa操作数据库 级联数据 hibernate

    例如,`@OneToMany`和`@ManyToOne`用于表示一对多或多对一的关系,级联操作如`CascadeType.PERSIST`、`CascadeType.MERGE`等可以确保当一个实体被保存或更新时,与其关联的实体也会相应更新。这在处理关联数据时非常...

    jpa 关联映射jpa 关联映射jpa 关联映射

    通过以上示例,我们了解了如何在 JPA 中定义实体之间的关联关系,并且学习了如何使用 `@ManyToOne`、`@JoinColumn`、`@OneToMany` 等注解来描述实体之间的多对一和一对多关系。此外,还讨论了级联操作 (`cascade`) ...

    JPA一对多和多对一关系

    **JPA一对多和多对一关系详解** Java Persistence API(JPA)是Java平台上的一个标准,用于处理对象关系映射(ORM),使得开发者可以使用面向对象的方式来操作数据库。在JPA中,实体间的关系映射是核心概念之一,...

    jpa的实体映射关系7种

    在单向多对多关系中,一个实体可以关联多个其他实体,而这些实体并不知道这个关联。使用`@ManyToMany`注解,关联表通常由JPA自动创建,除非自定义了`@JoinTable`。 7. **双向多对多**: 双向多对多是最复杂的关系...

    JPA实体关联(hibernate实现)

    双向的一对一关联则需要在两个实体上都进行配置,但只有一个方向是“拥有”关系,用`@OneToOne(cascade=CascadeType...)`来指定级联操作。 4. **一对多关联(JPAOneToMany)** 一对多关联意味着一个实体可以与多个...

    Hibernate- oneToMany using annotation

    在Java的持久化框架Hibernate中,`@OneToMany`注解是用于表示一对多关系的,这种关系常见于数据库设计中的父表与子表之间。在这个主题中,我们将深入探讨如何在实体类中使用`@OneToMany`注解以及其在实际项目中的...

    实用JPA开发指南----jpa核心技术(关联关系等的配置高级配置)

    2. **级联操作(Cascading)**: 级联操作允许在一个实体的操作(如保存、删除)影响到与其关联的其他实体。`CascadeType`枚举提供了多种级联类型。 3. **外键约束(Foreign Key Constraints)**: JPA支持声明外键...

    JPA学习笔记-EJB-04JPA关联映射总结

    4. `@ManyToMany`:多对多关系,多个实体可以关联多个其他实体,通常需要一个中间表来存储关系。 在实际应用中,JPA的关联映射不仅可以简化对象关系映射的配置,还能提供诸如级联操作(`@CascadeType`)和懒加载(`...

    jpa to many

    // 多对一关系,外键在ChildEntity中 @ManyToOne @JoinColumn(name = "parent_id") private ParentEntity parent; } ``` 在这个例子中,`ParentEntity`与`ChildEntity`之间是一对多的关系,`ParentEntity`的`...

    Hibernate 注解一对多,多对一

    本文将深入探讨Hibernate中的两个关键概念——注解声明的一对多(@OneToMany)和多对一(@ManyToOne)关系,以及如何在实际项目中应用它们。 一、Hibernate注解介绍 Hibernate通过注解简化了Java类与数据库表之间的...

    oneToMany.rar

    在Spring JPA中,`OneToMany`关系映射是数据库中实体之间常见的一种关联类型,它表示一个实体可以与多个其他实体相关联。本教程将深入探讨`OneToMany`映射的概念、配置以及在实际开发中的应用。 `OneToMany`关系...

Global site tag (gtag.js) - Google Analytics