Hibernate框架【五】——基本映射——多对多映射

简介: Hibernate框架【五】——基本映射——多对多映射

系列文章目录

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

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

基本映射——多对多映射


前言

由于公司项目上进行面向对象的架构设计对于ORM部分使用的是Spring Data JPA框架。将ORM完全交给Spring Data JPA框架,而Hibernate是Spring Data JPA的实现方式之一,通过对HIbernate框架的学习能够更好的理解ORM框架,以及Spring Data JPA框架。

下面的博客是对于Hibernate框架中的基本映射中的一对一映射进行的实践,总结的并不全面,旨在对于一对一映射关系有一个宏观了解并能够进行基本运用。


一、多对多映射是什么?

在Hibernate中,多对多映射表示多个实体之间的多对多关系,其中一个实体可以与多个另一实体相关联,并且每个另一实体也可以与多个该实体相关联。

在多对多映射中,需要创建一个中间表(关联表)来存储实体之间的关联关系。该中间表通常包含两个外键列,分别指向参与关联的两个实体的主键。

当然多对多映射关系,也分为单向关联和双向关联。


二、hibernate多对多关联映射(单向)

案例:现在有两个实体User实体和Role,分别表现出多对多的关系,一个用户可以有多个角色,一个角色可以包含多个用户。


1.实体结构

package com.wangwei.hibernate;
import java.util.Set;
public class User {
    private int id;
    private String name;
    private Set roles;
    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 getRoles() {
        return roles;
    }
    public void setRoles(Set roles) {
        this.roles = roles;
    }
}
package com.wangwei.hibernate;
public class Role {
    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;
    }
}

2.示意图

3.对应的实体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.Role" table="t_role">
        <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"/>
        <set name="roles" table="t_user_role">
            <key column="user_id"/>
            <many-to-many class="com.wangwei.hibernate.Role" column="role_id" />    
        </set>
    </class>
</hibernate-mapping>

4.生成的表结构

5.核心代码

1.插入数据

public class Many2ManyTest extends TestCase {
    public void testSave1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Role r1 = new Role();
            r1.setName("数据录入人员");
            session.save(r1);
            Role r2 = new Role();
            r2.setName("商务主管");
            session.save(r2);
            Role r3 = new Role();
            r3.setName("商务经理");
            session.save(r3);
            Role r4 = new Role();
            r4.setName("项目会计");
            session.save(r4);
            User u1 = new User();
            u1.setName("张三");
            Set u1Roles = new HashSet();
            u1Roles.add(r1);
            u1Roles.add(r2);
            u1.setRoles(u1Roles);
            session.save(u1);
            User u2 = new User();
            u2.setName("李四");
            Set u2Roles = new HashSet();
            u2Roles.add(r1);
            u2Roles.add(r2);
            u2Roles.add(r3);
            u2.setRoles(u2Roles);
            session.save(u2);
            User u3 = new User();
            u3.setName("王五");
            Set u3Roles = new HashSet();
            u3Roles.add(r3);
            u3Roles.add(r4);
            u3.setRoles(u3Roles);
            session.save(u3);
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }    

发出的SQL语句

数据库中的数据

2.查询数据

public void testLoad1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            User user = (User)session.load(User.class, 2);
            System.out.println(user.getName());
            for (Iterator iter=user.getRoles().iterator(); iter.hasNext();) {
                Role role = (Role)iter.next();
                System.out.println(role.getName());
            }
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }        

发出的sql语句和打印的结果

三、hibernate多对多关联映射(双向)

1.实体结构

package com.wangwei.hibernate;
import java.util.Set;
public class Role {
    private int id;
    private String name;
    private Set User;
    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 getUser() {
        return User;
    }
    public void setUser(Set user) {
        User = user;
    }
}
package com.wangwei.hibernate;
import java.util.Set;
public class User {
    private int id;
    private String name;
    private Set roles;
    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 getRoles() {
        return roles;
    }
    public void setRoles(Set roles) {
        this.roles = roles;
    }
}

2.对应实体的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.Role" table="t_role">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="user" table="t_user_role">
            <key column="role_id" not-null="true"/>
            <many-to-many class="com.wangwei.hibernate.User" column="user_id"/>
        </set>
    </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"/>
        <set name="roles" table="t_user_role">
            <key column="user_id"/>
            <many-to-many class="com.wangwei.hibernate.Role" column="role_id" />    
        </set>
    </class>
</hibernate-mapping>

注意事项:

  • 生成的中间表名称必须一样
  • 生成的中间表中的字段必须一样

3.生成的表结构

4.核心代码

1.插入数据

public void testSave1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Role r1 = new Role();
            r1.setName("数据录入人员");
            session.save(r1);
            Role r2 = new Role();
            r2.setName("商务主管");
            session.save(r2);
            Role r3 = new Role();
            r3.setName("商务经理");
            session.save(r3);
            Role r4 = new Role();
            r4.setName("项目会计");
            session.save(r4);
            User u1 = new User();
            u1.setName("张三");
            Set u1Roles = new HashSet();
            u1Roles.add(r1);
            u1Roles.add(r2);
            u1.setRoles(u1Roles);
            session.save(u1);
            User u2 = new User();
            u2.setName("李四");
            Set u2Roles = new HashSet();
            u2Roles.add(r1);
            u2Roles.add(r2);
            u2Roles.add(r3);
            u2.setRoles(u2Roles);
            session.save(u2);
            User u3 = new User();
            u3.setName("王五");
            Set u3Roles = new HashSet();
            u3Roles.add(r3);
            u3Roles.add(r4);
            u3.setRoles(u3Roles);
            session.save(u3);
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }    

生成的sql语句

表中的数据

2.查询数据(先查User)

public void testLoad1() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            User user = (User)session.load(User.class, 2);
            System.out.println(user.getName());
            for (Iterator iter=user.getRoles().iterator(); iter.hasNext();) {
                Role role = (Role)iter.next();
                System.out.println(role.getName());
            }
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }        

发出的sql语句和打印的结果

3.查询数据(先查Role)

public void testLoad2() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Role role = (Role)session.load(Role.class, 1);
            System.out.println(role.getName());
            for (Iterator iter=role.getUser().iterator(); iter.hasNext();) {
                User user = (User)iter.next();
                System.out.println(user.getName());
            }
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }        

发出的sql语句和结果

四、总结

如何选择多对多的单向关联还是多项关联。主要取决于实际的业务需要。

1.如果只需要从一个实体导航到另一个实体,而无需反向导航,那么使用单向关联更为合适。

2.如果不需要再两个实体上进行关系的维护,添加、删除、更新等,那么单向关联更合适。

3.维护上:单向关联不会引入额外的的关系

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
1月前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
18 1
|
3月前
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
64 4
|
4月前
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
60 1
|
4月前
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
91 0
|
4月前
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
55 0
|
4月前
|
数据库 Java 数据库连接
Struts 2 与 Hibernate 的完美邂逅:如何无缝集成两大框架,轻松玩转高效 CRUD 操作?
【8月更文挑战第31天】本文通过具体示例介绍了如何在 Struts 2 中整合 Hibernate,实现基本的 CRUD 操作。首先创建 Maven 项目并添加相关依赖,接着配置 Hibernate 并定义实体类及其映射文件。然后创建 DAO 接口及实现类处理数据库操作,再通过 Struts 2 的 Action 类处理用户请求。最后配置 `struts.xml` 文件并创建 JSP 页面展示用户列表及编辑表单。此示例展示了如何配置和使用这两个框架,使代码更加模块化和可维护。
145 0
|
5月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
91 0
|
6月前
|
Java 数据库连接 数据库
探索JPA生态:Hibernate与其他ORM框架的对比分析
【6月更文挑战第25天】**JPA标准下的Hibernate是流行的ORM实现,提供丰富功能如二级缓存和延迟加载,但其学习曲线较陡,性能优化复杂。相比如MyBatis,Hibernate的JPQL更面向对象,MyBatis则接近SQL。选择ORM需考虑项目需求和个人偏好。**
98 0
|
7月前
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
6月前
|
Java 数据库连接
杨老师课堂之JavaEE三大框架Hibernate入门第一课
杨老师课堂之JavaEE三大框架Hibernate入门第一课
35 0