Hibernate框架【四】——基本映射——多对一和一对多映射

news2024/11/24 0:06:14

系列文章目录

Hibernate框架【三】——基本映射——一对一映射


基本映射——多对一和一对多映射

  • 系列文章目录
  • 前言
  • 一、多对一映射是什么?
    • 1.案例:现在有两个实体User实体和Group,其中多个User属于一个Group,表现出多对一的关系。
      • ①.实体结构
      • ②.实体对象的xml配置
      • ③.什么是级联?
      • ④.生成的表结构
      • ⑤.往表中插入数据
      • ⑥.查询数据
  • 二、一对多映射是什么?
    • 1.案例:现在有两个实体Classes实体和Student,其中一个班级包含多个学生,表现出一对多的关系。
      • ①实体结构
      • ②.实体对应的xml配置
      • ③.生成的表结构
      • ④.插入数据
      • ⑤.查询数据
  • 总结


前言

由于公司项目上进行面向对象的架构设计对于ORM部分使用的是Spring Data JPA框架。将ORM完全交给Spring Data JPA框架,而Hibernate是Spring Data JPA的实现方式之一,通过对HIbernate框架的学习能够更好的理解ORM框架,以及Spring Data JPA框架。
下面的博客是对于Hibernate框架中的基本映射中的多对一和一对多映射进行的实践,总结的并不全面,旨在多对一和一对多映射关系有一个宏观了解并能够进行基本运用。


一、多对一映射是什么?

在 Hibernate 中,多对一关联映射表示多个实体关联到另一个实体,即多个从实体关联到一个主实体。这种关系常用于表示层级关系或父子关系。
在多对一关联映射中,存在两个实体,即主实体和从实体。从实体包含对主实体的引用,而主实体通常是拥有外键的一方。

1.案例:现在有两个实体User实体和Group,其中多个User属于一个Group,表现出多对一的关系。

①.实体结构

package com.wangwei.hibernate;

import java.util.Date;

public class User {
    
private Integer id;
    
    private String name;
    
    private Group group;

    

    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 Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }  
}

package com.wangwei.hibernate;

import java.util.Date;

public class Group {
    
private Integer id;
    
    private String name;
    
    

    

    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;
    }
}

②.实体对象的xml配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wangwei.hibernate.Group" table="t_group">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        
    </class>
    
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wangwei.hibernate.User" table="t_user">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <many-to-one name="group" column="groupid" cascade="save-update"/>
    </class>
    
</hibernate-mapping>

备注:
在多的一端采用如下标签映射:

<many-to-one name="group" column="groupid"/>

③.什么是级联?

级联是对象之间的连锁操作,它只影响添加、删除和修改
cascade表示级联操作:
常见的级联操作类型:级联保存:当一个实体进行保存操作是,级联保存将自动保存与该实体关联的所有实体。这样可以避免手动保存关联实体的麻烦。
级联更新、级联删除、级联刷新(当一个实体执行刷新操作时,级联刷新将自动刷新与该实体关联的所有实体,确保关联实体的数据与数据库中的数据保存一致)。
除了上面的一些操作之外,还可以进行组合如:级联保存更新、级联保存删除等等。

④.生成的表结构

在这里插入图片描述
在这里插入图片描述

⑤.往表中插入数据

核心代码:

public void saveTest3() {
        Session session =null;
        
        try {
            session=HibernateUtils.getSession();
            session.beginTransaction();
            
            Group group=new Group();
            group.setName("廊坊师范学院");
            
            
            User user1=new User();
            user1.setName("wangwei");
            user1.setGroup(group);
            
            User user2=new User();
            user2.setName("lyy");
            user2.setGroup(group);
            
            session.save(user1);
            session.save(user2);
            //使用了级联特性
            //hibernate会首先保存User的关联对象 Group
            //Group和User都是Persistent状态的对象了
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
        }

生成的sql语句
在这里插入图片描述
对应表中的数据
在这里插入图片描述
在这里插入图片描述

⑥.查询数据

核心代码:

public void loadTest1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            User user = (User)session.load(User.class, 1);
            System.out.println("user.name=" + user.getName());
            System.out.println("user.group.name=" + user.getGroup().getName());
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
        }

生成的sql语句和打印出的数据
在这里插入图片描述

二、一对多映射是什么?

在 Hibernate 中,一对多关联表示一个实体与多个关联实体之间的关系,其中一个实体拥有对多个关联实体的引用。这种关联关系通常使用集合来表示。
在一对多关联中,存在两个实体,即主实体和从实体。主实体拥有对从实体的集合引用,而从实体则包含一个对主实体的引用。

1.案例:现在有两个实体Classes实体和Student,其中一个班级包含多个学生,表现出一对多的关系。

①实体结构

package com.wangwei.hibernate;

import java.util.Set;

public class Classes {
    
    private int id;
    
    private String name;
    
    private Set students;

    public int getId() {
        return id;
    }

    public void setId(int 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;
    }
    
}

package com.wangwei.hibernate;

public class Student {

    private int id;
    
    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

②.实体对应的xml配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wangwei.hibernate.Student" table="t_student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
    </class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wangwei.hibernate.Classes" table="t_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="students">
            <!-- 
            <key column="classesid" not-null="true"/>
             -->
             <key column="classesid"/>
            <one-to-many class="com.wangwei.hibernate.Student"/>
        </set>
    </class>
</hibernate-mapping>

③.生成的表结构

在这里插入图片描述
在这里插入图片描述

④.插入数据

核心代码:

public void testSave2() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Student student1 = new Student();
            student1.setName("张三");
            session.save(student1);
            
            Student student2 = new Student();
            student2.setName("李四");
            session.save(student2);
            
            Classes classes = new Classes();
            classes.setName("计算机");
            
            Set students = new HashSet();
            students.add(student1);
            students.add(student2);
            classes.setStudents(students);
            
            //可以成功保存数据
            //但是会发出多余的update语句来维持关系
            session.save(classes);
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }    

发出的sql语句:
在这里插入图片描述
对应数据表中的数据:
在这里插入图片描述
在这里插入图片描述

⑤.查询数据

核心代码:

public void testLoad1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Classes classes = (Classes)session.load(Classes.class, 1);
            System.out.println("classes.name=" + classes.getName());
            Set students = classes.getStudents();
            for (Iterator iter=students.iterator(); iter.hasNext();) {
                Student student = (Student)iter.next();
                System.out.println("student.name=" +student.getName());
            }
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }        

发出的sql语句和打印出的内容:
在这里插入图片描述

总结

  1. 一对多关联映射和多对一关联映射映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。

  2. 与多对一不同的是,一对多维护的关系是:有一的一端维护关系,一指向多的关系,有了此关系,在加载一的时候可以将多加载上来。

  3. 但是一的一端维护关系存在缺陷:
    因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)
    所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则
    将无法保存数据

  4. 另外因为Student不维护关系,而Classes维护关系,Classes就会发出多余的update语句,保证
    Classes和Student有关系,这样加载Classes的时候才可以把该Classes对应的学生加载上来。发出多余的update语句本身效率上还是有些问题的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图解LeetCode——98. 验证二叉搜索树

一、题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 二、示例 2.1>…

扫描出项目中未被引用的控制器接口的工具类(超级好用)

自己的项目随着不断开发迭代&#xff0c;越来越庞大&#xff0c;后台的接口也就越来越多&#xff0c;难免会有一些接口后来并没有使用到&#xff0c;但是还在代码中&#xff0c;权限管理的时候这部分接口是非常多余的&#xff0c;为了避免这个问题&#xff0c;本章提供了一个工…

回归测试最小化(贪心算法,帕累托支配)

回归测试最小化(贪心算法,帕累托支配) 介绍 有时我们不能只是重新运行我们的测试&#xff08;例如&#xff0c;当我们 换界面&#xff09;。 回归测试可能很昂贵: (1)一些公司通宵运行回归测试套件。 (2) 对于嵌入式系统&#xff0c;我们可能必须测试正在使用的软件&#xff0…

党校学员毕业自我鉴定总结样文分享

党校学员毕业自我鉴定总结样文分享1 岁月匆匆似流水&#xff0c;美好的研究生三年时光马上就快结束了。经过良师的悉心指导以及自己的努力奋力拚搏、自强不息&#xff0c;我渐渐的成为了一个能适应现代社会要求的硕士毕业生&#xff0c;并为做一个知识型的社会主义建设者打下坚…

Web应用技术(第十四周/END)

本次练习基于how2j和课本,初步认识Spring。 以后我每周只写一篇Web的博客&#xff0c;所有的作业内容会在这篇博客中持续更新。。。 一、Spring基础1.Spring概述:2.Sring组成&#xff1a;3.BeanFactory&#xff1a;4.控制反转&#xff1a;5.依赖注入&#xff1a;6.JavaBean与S…

oracle数据库sequence的作用

sequence概念及作用 sequence是用来在多用户环境下产生唯一整数的数据库对象。序列产生器顺序生成数字&#xff0c;它可用于自动生成主键值&#xff0c;并能协调多行或者多表的主键操 作。没有sequence&#xff0c;顺序的值只能靠编写程序来生成。先找出最近产生的值然后自增长…

零基础初学前端—新建项目

对于一个没有基础的新手来说&#xff0c;如何使用 vscode 新建一个前端项目&#xff0c;写一些html页面&#xff0c;并能进行运行。 需要吐下几个步骤&#xff1a; 新建一个文件夹在文件夹里新建一个文件&#xff0c;命名为 xxx.html &#xff0c;例如 index.html打开 vscode …

前端:使用rollup的简单记录

目录 rollup安装 简单使用 1、命令行打包 2、配置文件打包 问题 1、报错提示&#xff1a;(node:23744) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.(Use node --trace-warnings ... to sho…

模拟电子 | 稳压管及其应用

模拟电子 | 稳压管及其应用 稳压二极管工作在反向击穿状态时&#xff0c;其两端的电压是基本不变的。利用这一性质&#xff0c;在电路里常用于构成稳压电路。 稳压二极管构成的稳压电路&#xff0c;虽然稳定度不很高&#xff0c;输出电流也较小&#xff0c;但却具有简单、经济实…

IDEA(版本2020)启动错误

错误信息&#xff1a;在运行Java应用程序时&#xff0c;发现没有找到Java虚拟机(JVM)&#xff0c;并且需要手动设置JAVA_HOME环境变量。 idea启动时的提示如下&#xff1a; 解决方案如下&#xff1a; 确认已经安装了64位JDK&#xff0c;并且JDK的bin目录已经被添加到了系统的环…

YOLO算法入门知识概念

1.two-stage && one-stage two-stage(两阶段)&#xff1a;Faster-rcnn,Mask-Rcnn系列&#xff08;5EPS&#xff09;---多了预选环节 one-stage(单阶段)&#xff1a;YOLO系列&#xff08;速度快&#xff09;---实时检测时常用2.Map指标&#xff1a;综合衡量控制效果 包…

Android基站定位源代码

经过几天的调研以及测试&#xff0c;终于解决了联通2G、移动2G、电信3G的基站定位代码。团队里面只有这些机器的制式了。下面就由我来做一个详细的讲解吧。1 相关技术内容 Google Android Api里面的TelephonyManager的管理。 联通、移动、电信不同制式在获取基站位置的代码区别…

开源赋能 普惠未来|TKEStack 诚邀您参与 2023 开放原子全球开源峰会

TKEStack 是腾讯开源的一款集强壮性和易用性于一身的企业级容器编排引擎&#xff0c;以极简的向导式界面为用户提供了容器应用全生命周期管理能力&#xff0c;帮助用户在私有云环境中快速构建 PAAS 容器云平台&#xff0c;并敏捷、高效地管理和发布应用程序。作为完全开放的项目…

华秋硬创 | 全国科技工作者日,致敬每一位科技创新者!

2023年5月30日是第七个“全国科技工作者日”&#xff0c;“全国科技工作者日”的设立旨在弘扬科学家精神&#xff0c;团结引导广大科技工作者厚植家国情怀、勇于创新争先。 今年&#xff0c;全国科技工作者日主题是“点亮精神火炬”。每一次科学探索&#xff0c;都始于一束心中…

ipad手写笔哪个牌子好用?便宜的ipad触控笔

在这无纸化的时代&#xff0c;越来越多人向往简便、快速&#xff0c;人们会更想有自己的能够快速完成&#xff0c;电容笔是出现&#xff0c;深受大众喜欢&#xff0c;随着电容笔技术的不断进步&#xff0c;电容笔越来越普遍&#xff0c;价格也越来越低&#xff0c;使用效果也越…

建造者模式的学习与使用以及和抽象工厂模式的区别

1、建造者模式的学习 当创建一个复杂对象时&#xff0c;使用建造者模式可以将对象的构建过程和表示分离开来。它允许使用相同的构建过程来创建不同的表示形式。   建造者模式的主要思想是将一个复杂对象的构建过程分解为一系列简单的步骤&#xff0c;并且使用一个指导者&…

14届蓝桥杯青少组省赛(中级组)C++_2023.5.14

选择题: 1、设只含根结点的二叉树高度为1,共有62个结点的完全二叉树的高度为?(C) A.4 B.5 C.6 D.7 2、C++中,bool类型的变量占用字节字数为?(A) A.1 B.2 C.3 D.4 3、该程序的输出为?(A) A.127 B.97 C.63 D.126 4、以下关于数组的说法中…

力扣-根据前序和后序遍历构造二叉树(java)

根据前序和后序遍历构造二叉树 leetcode 889 题&#xff08;中等&#xff09;解题思路代码演示二叉树专题 leetcode 889 题&#xff08;中等&#xff09; 原题链接&#xff1a; https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal/ 题…

echart实现地图展示

最近做的页面中需要展示省级地图精确到市级且悬浮到地区上时会显示一些信息 然后参考了网址&#xff1a; “绿色金融” - 江西省 - category-work,geo地理坐标,legend,series-map地图,series-scatter散点图,title标题,tooltip提示框,visualMap视觉映射 - makeapie echarts社区…

同心旋转圆弧

效果如图: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…