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

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

系列文章目录

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


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

前言

由于公司项目上进行面向对象的架构设计对于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. 但是一的一端维护关系存在缺陷:
  4. 因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)
  5. 所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则
  6. 将无法保存数据

  7. 另外因为Student不维护关系,而Classes维护关系,Classes就会发出多余的update语句,保证
  8. Classes和Student有关系,这样加载Classes的时候才可以把该Classes对应的学生加载上来。发出多余的update语句本身效率上还是有些问题的。
相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
目录
相关文章
|
2天前
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
2天前
|
SQL 缓存 Java
Java一分钟之-Hibernate:ORM框架实践
【5月更文挑战第15天】Hibernate是Java的ORM框架,简化数据库操作。本文列举并解决了一些常见问题: 1. 配置SessionFactory,检查数据库连接和JDBC驱动。 2. 实体类需标记主键,属性映射应匹配数据库列。 3. 使用事务管理Session,记得关闭。 4. CRUD操作时注意对象状态和查询结果转换。 5. 使用正确HQL语法,防止SQL注入。 6. 根据需求配置缓存。 7. 懒加载需在事务内处理,避免`LazyInitializationException`。理解和避免这些问题能提升开发效率。
19 0
|
2天前
|
SQL Java 数据库连接
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
|
2天前
|
SQL Java 关系型数据库
数据库访问:什么是Hibernate框架?
【4月更文挑战第15天】Hibernate是开源ORM框架,将Java对象与数据库表映射,简化对象-关系映射,提升开发效率和性能。它自动化处理数据操作,支持多种数据库,自动生成SQL,提供配置选项和高级特性,减少手动SQL编写,便于切换数据库。
26 2
|
2天前
|
SQL XML Java
Hibernate - 单向多对一关联关系映射
Hibernate - 单向多对一关联关系映射
16 0
|
8月前
|
Java 数据库连接
简述使用Hibernate框架的几个步骤
简述使用Hibernate框架的几个步骤
41 0
|
9月前
|
SQL Java 关系型数据库
Hibernate框架概述
Hibernate框架概述
81 0
|
10月前
|
SQL 缓存 Oracle
Hibernate框架【一】——HIbernate框架介绍
Hibernate框架【一】——HIbernate框架介绍
180 0
|
10月前
|
SQL XML 存储
Hibernate框架【五】——基本映射——多对多映射
Hibernate框架【五】——基本映射——多对多映射
133 0
|
10月前
|
XML 存储 Java
Hibernate框架【三】——基本映射——一对一映射
Hibernate框架【三】——基本映射——一对一映射
49 0