热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

Hibernate关系映射级联操作

Hibernate关系映射-级联操作cascade在双向一对多的学习中,我们发现每次保存对象时,学生对象和年纪对象都需要我们持久化之session,既然它们两者有关联关系,可不可以

Hibernate关系映射-级联操作cascade

在双向一对多的学习中,我们发现每次保存对象时,学生对象和年纪对象都需要我们持久化之session,既然它们两者有关联关系,可不可以只持久化其中一端,另一端就会自动的被持久化呢,这个属性就是Hibernate的cascade。cascade是多对一、一对多、一对一、多对多各种关系之间的一种级联操作行为。(关键语句:cascade="save-update"。)


一、什么是级联操作

官方解释:必须级联到关联目标的操作,默认情况下没有级联操作。

当Hibernate持久化一个瞬时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,而是会抛出org.hibernate.TransientObjectException。

级联的意思是:本实体做了什么事,也要拉上另一个关联的实体,导致另一个实体跟着做事情。就是说我删除了,你也必须删除!关联目标,指的是关联的那个实体 。


二、准备案例

在明确了级联操作的概念知识以后,使用学生表和年纪表的双向一对多关系,实现级联操作行为。

学生表和年纪表的双向一对多关系学习请参考(Hibernate关系映射-双向一对多)。

cascade级联操作,默认是none不级联。

none:不级联。

save-update:保存和更新某一端数据时,另一端数据可以一起保存和更新。

delete:删除级联-不能在多的一端使用。

all:表示所有操作都级联


三、实现级联操作

1、配置多端



  1. 编写配置文件

    Student.hbm.xml

    xml version="1.0" encoding="UTF-8" ?>
    DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"
    >

    <hibernate-mapping package="com.uestc">
    <class name="Student">
    <id name="id">
    <generator class="native"/>
    id>
    <property name="name"/>
    <property name="age"/>

    <many-to-one cascade="save-update" name="grade" class="Grade"
    column
    ="grade_id" foreign-key="fk_grade"/>
    class>
    hibernate-mapping>

     

    2.编写Grade.hbm.xml

    xml version="1.0" encoding="UTF-8" ?>
    DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"
    >

    <hibernate-mapping package="com.uestc">
    <class name="Grade">
    <id name="id">
    <generator class="native"/>
    id>
    <property name="name"/>

    <set name="students" cascade="save-update">
    <key foreign-key="fk_grade" column="grade_id">key>
    <one-to-many class="Student"/>
    set>
    class>
    hibernate-mapping>

     



    1. Student类



    public class Student implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private Grade grade;

    @Override
    public String toString() {
    return "Student{" +
    "id=" + id +
    ", name='" + name + '\'' +
    ", age=" + age +
    ", grade=" + grade +
    '}';
    }

    public Integer getId() {
    return id;
    }

    public void setId(Integer id) {
    this.id = id;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public Integer getAge() {
    return age;
    }

    public void setAge(Integer age) {
    this.age = age;
    }

    public Grade getGrade() {
    return grade;
    }

    public void setGrade(Grade grade) {
    this.grade = grade;
    }
    }

     



    1. Grade类

      public class Grade implements Serializable {
      private Integer id;
      private String name;
      private Set students = new HashSet<>();

      @Override
      public String toString() {
      return "Grade{" +
      "id=" + id +
      ", name='" + name + '\'' +
      ", students=" + students +
      '}';
      }

      public Integer getId() {
      return id;
      }

      public void setId(Integer id) {
      this.id = id;
      }

      public String getName() {
      return name;
      }

      public void setName(String name) {
      this.name = name;
      }

      public Set getStudents() {
      return students;
      }

      public void setStudents(Set students) {
      this.students = students;
      }
      }

       



      1. 编写hibernate.cfg.xml

        xml version="1.0" encoding="utf-8" ?>
        DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"
        >

        <hibernate-configuration>
        <session-factory>

        <property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
        <property name="connection.url">jdbc:mysql:///hibernateproperty>
        <property name="connection.username">rootproperty>
        <property name="connection.password">rootproperty>

        <property name="dialect">org.hibernate.dialect.MySQL8Dialectproperty>

        <property name="hbm2ddl.auto">updateproperty>

        <property name="show_sql">trueproperty>

        <property name="format_sql">trueproperty>

        <mapping resource="com/uestc/Grade.hbm.xml"/>
        <mapping resource="com/uestc/Student.hbm.xml"/>
        session-factory>
        hibernate-configuration>

         



        1. 测试类

          /**
          * 单向多对一
          */
          @Test
          public void testSingleManyToOne() {
          Session session
          = null;
          Transaction tx
          = null;
          try {
          session
          = HibernateUtil.getSession();
          tx
          = session.beginTransaction();

          //创建实例对象
          Grade grade1 = new Grade();
          grade1.setName(
          "基础");

          Grade grade2
          = new Grade();
          grade2.setName(
          "中级");



          Student student
          = new Student();
          student.setName(
          "张三");
          student.setAge(
          18);
          student.setGrade(grade1);

          Student student2
          = new Student();
          student2.setName(
          "李四");
          student2.setAge(
          18);
          student2.setGrade(grade1);

          Student student3
          = new Student();
          student3.setName(
          "王五");
          student3.setAge(
          18);
          student3.setGrade(grade2);

          //存储的顺序是根据外键约束而定的,如果外键不可以为空,必须先存储外键的一端
          //如果外键可以为空,随意存储,但是建议先存储外键的一端,因为会多执行update
          // session.save(grade1);
          // session.save(grade2);

          session.save(student);
          session.save(student2);
          session.save(student3);



          tx.commit();

          }
          catch (Exception e){
          e.printStackTrace();
          tx.rollback();
          }
          finally {
          HibernateUtil.closeSession();
          }
          }

          /**
          * 获取
          * 查询不用开启事务,会降低性能
          */
          @Test
          public void testSingleGetManyToOne() {
          Session session
          = null;
          Transaction tx
          = null;
          try {
          session
          = HibernateUtil.getSession();
          tx
          = session.beginTransaction();

          Student student
          = session.get(Student.class,1);
          System.out.println(
          "stuName:" +student.getName() + ",grade:" +student.getGrade().getName());


          tx.commit();

          }
          catch (Exception e){
          e.printStackTrace();
          tx.rollback();
          }
          finally {
          HibernateUtil.closeSession();
          }
          }

          /**
          * 单向一对多
          */
          @Test
          public void testSingleOneToMany() {
          Session session
          = null;
          Transaction tx
          = null;
          try {
          session
          = HibernateUtil.getSession();
          tx
          = session.beginTransaction();

          //创建实例对象

          Student student
          = new Student();
          student.setName(
          "张三");
          student.setAge(
          18);

          Student student2
          = new Student();
          student2.setName(
          "李四");
          student2.setAge(
          18);


          Student student3
          = new Student();
          student3.setName(
          "王五");
          student3.setAge(
          18);

          Grade grade1
          = new Grade();
          grade1.setName(
          "基础");
          grade1.getStudents().add(student);
          grade1.getStudents().add(student2);

          Grade grade2
          = new Grade();
          grade2.setName(
          "中级");
          grade2.getStudents().add(student3);

          //存储的顺序是根据外键约束而定的,如果外键不可以为空,必须先存储外键的一端
          //单向一对多会多执行update语句,效率不如多对一
          session.save(grade1);
          session.save(grade2);

          // session.save(student);
          // session.save(student2);
          // session.save(student3);


          tx.commit();

          }
          catch (Exception e){
          e.printStackTrace();
          tx.rollback();
          }
          finally {
          HibernateUtil.closeSession();
          }
          }

          /**
          * 获取
          * 查询不用开启事务,会降低性能
          */
          @Test
          public void testSingleGetOneToMany() {
          Session session
          = null;
          Transaction tx
          = null;
          try {
          session
          = HibernateUtil.getSession();
          tx
          = session.beginTransaction();

          Student student
          = session.get(Student.class,1);
          System.out.println(
          "stuName:" +student.getName() + ",grade:" +student.getGrade().getName());
          System.out.println(
          "---------------------分割线-------------------");
          Grade grade
          = session.get(Grade.class,1);
          System.out.println(
          "grade:" +grade.getName());
          for(Student stu : grade.getStudents()){
          System.out.println(
          "stuName:" +stu.getName());
          }



          tx.commit();

          }
          catch (Exception e){
          e.printStackTrace();
          tx.rollback();
          }
          finally {
          HibernateUtil.closeSession();
          }

          }

           










四、总结

大家可以尝试除了新增以外的其他操作,可以得出以下结论



  • 在多对一的关系中,多的一端不能操作级联为delete,一般在多的一端设为save-update;



  • 在一对多的关系中,如果一的一端设为delete相关配置时,多的一端不能指明外键为非空。





推荐阅读
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 解决FCKeditor应用主题后上传问题及优化配置
    本文介绍了在Freetextbox收费后选择FCKeditor作为替代方案时遇到的上传问题及其解决方案。通过调整配置文件和调试工具,最终解决了上传失败的问题,并对相关配置进行了优化。 ... [详细]
  • 深入理解 .NET 中的中间件
    中间件是插入到应用程序请求处理管道中的组件,用于处理传入的HTTP请求和响应。它在ASP.NET Core中扮演着至关重要的角色,能够灵活地扩展和自定义应用程序的行为。 ... [详细]
  • 解决Windows 10开机频繁自检问题的实用方法
    许多用户在使用Windows 10系统时,经常会遇到开机时自动进行磁盘检查的情况。这不仅影响了开机速度,还可能带来不必要的麻烦。本文将详细介绍如何通过简单的注册表修改来避免每次开机时的磁盘自检,提升系统启动效率。 ... [详细]
  • 本文详细介绍了在使用 SmartUpload 组件进行文件上传时,如何正确配置和查找文件保存路径。通过具体的代码示例和步骤说明,帮助开发者快速解决上传路径配置的问题。 ... [详细]
  • Python + Pytest 接口自动化测试中 Token 关联登录的实现方法
    本文将深入探讨 Python 和 Pytest 在接口自动化测试中如何实现 Token 关联登录,内容详尽、逻辑清晰,旨在帮助读者掌握这一关键技能。 ... [详细]
  • 本文探讨了在Django项目中,如何在对象详情页面添加前后导航链接,以提升用户体验。文章详细描述了遇到的问题及解决方案。 ... [详细]
  • 本文探讨了在 SQL Server 中使用 JDBC 插入数据时遇到的问题。通过详细分析代码和数据库配置,提供了解决方案并解释了潜在的原因。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • CEC2005 F4函数实现中的Bug分析
    本文探讨了在optproblems版本1.2中,CEC2005基准测试包中F4函数的实现问题。根据Suganthan等人的论文,F4函数的高斯部分应取绝对值,但当前实现未遵循这一要求,导致理论最优解并非-450。本文通过代码截图详细说明了这一问题,并提供了进一步的解释。 ... [详细]
  • 本文详细介绍如何使用 Apache Spark 执行基本任务,包括启动 Spark Shell、运行示例程序以及编写简单的 WordCount 程序。同时提供了参数配置的注意事项和优化建议。 ... [详细]
  • CentOS 6.8 上安装 Oracle 10.2.0.1 的常见问题及解决方案
    本文记录了在 CentOS 6.8 系统上安装 Oracle 10.2.0.1 数据库时遇到的问题及解决方法,包括依赖库缺失、操作系统版本不兼容、用户权限不足等问题。 ... [详细]
  • Django Token 认证详解与 HTTP 401、403 状态码的区别
    本文详细介绍了如何在 Django 中配置和使用 Token 认证,并解释了 HTTP 401 和 HTTP 403 状态码的区别。通过具体的代码示例,帮助开发者理解认证机制及权限控制。 ... [详细]
  • 本文介绍了如何利用TensorFlow框架构建一个简单的非线性回归模型。通过生成200个随机数据点进行训练,模型能够学习并预测这些数据点的非线性关系。 ... [详细]
  • 本文介绍如何配置SecureCRT以正确显示Linux终端的颜色,并解决中文显示问题。通过简单的步骤设置,可以显著提升使用体验。 ... [详细]
author-avatar
指尖青春_388
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有