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

news/2024/11/24 22:48:34/

系列文章目录

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.ppmy.cn/news/139273.html

相关文章

Nginx通过用户IP获取所在国家及地理位置

文章目录 前言一、GeoLite2-Country是什么&#xff1f;二、使用步骤2.1 下载GeoLite2-Country数据库文件&#xff0c;并导入Nginx2.2 配置Nginx模块2.3 使用变量来获取国家信息2.4 验证配置 总结 前言 Nginx是一款高性能、轻量级的Web服务器和反向代理服务器。它最初设计目的是…

win11的docker-desktop安装

1、docker-desktop安装&#xff0c;参考 Windows系统上的Ubuntu wsl使用以及wsl连接远程服务器指南 - 知乎 a、官网直接下载安装&#xff08;2个地址任选&#xff09; https://www.docker.com/get-started/ https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20In…

液冷数据中心的液体为何物

大家都知道IT设备是不能碰水的&#xff0c;遇到水会出现短路的情况&#xff0c;IT设备运行会出现发热的问题&#xff0c;降温主要依靠风扇散热和空调制冷。对于大型数据中心来说&#xff0c;设备降温是一大难题&#xff0c;近年来出现了新型的液冷数据中心。 液冷数据中…

应用计算机散热的原理是什么,水冷散热器是什么原理?水冷可以带给机箱多大的散热作用?...

用户若是CPU安装了水冷散热器&#xff0c;就可以利用水快速导热和散热的特性加强主机硬件的散热效果&#xff0c;和普通风扇的散热效果相比&#xff0c;水冷可以更加有效的降低硬件温度和热量散发速度。阅读下文了解水冷散热器的原理和作用。 CPU水冷散热器是指使用液体在泵的带…

服务器液冷散热与风冷散热

液冷散热&#xff1a;液冷散热是把CPU的热量吸出来&#xff0c;通过液体降温达到散热的目的。也有将服务器完全放在液体下运行的模式。 液冷原理图 全浸式液冷服务器 风冷散热&#xff1a;风冷散热是通过散热器将CPU发出的热量转移至散热器块&#xff0c;然后通过风扇将热气吹走…

让用户真正放心的液冷技术来了

纵观人类历史&#xff0c;每次技术革新都伴随着生产要素和生产力的跨越式发展。如今&#xff0c;随着全球算力日益增长&#xff0c;数据中心单位空间中产生的热量正在不断增加、功率密度持续增大。赛迪顾问预测&#xff0c;快速增长的数据中心算力将推动高功率单机柜快速普及&a…

编写Java代码时应该避免的6个坑

通常情况下&#xff0c;我们都希望我们的代码是高效和兼容的&#xff0c;但是实际情况下代码中常常含有一些隐藏的坑&#xff0c;只有等出现异常时我们才会去解决它。本文是一篇比较简短的文章&#xff0c;列出了开发人员在编写 Java 程序时常犯的错误&#xff0c;避免线上问题…