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.维护上:单向关联不会引入额外的的关系

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
目录
相关文章
|
1天前
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
1天前
|
SQL 缓存 Java
Java一分钟之-Hibernate:ORM框架实践
【5月更文挑战第15天】Hibernate是Java的ORM框架,简化数据库操作。本文列举并解决了一些常见问题: 1. 配置SessionFactory,检查数据库连接和JDBC驱动。 2. 实体类需标记主键,属性映射应匹配数据库列。 3. 使用事务管理Session,记得关闭。 4. CRUD操作时注意对象状态和查询结果转换。 5. 使用正确HQL语法,防止SQL注入。 6. 根据需求配置缓存。 7. 懒加载需在事务内处理,避免`LazyInitializationException`。理解和避免这些问题能提升开发效率。
18 0
|
1天前
|
SQL Java 数据库连接
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
|
1天前
|
SQL Java 关系型数据库
数据库访问:什么是Hibernate框架?
【4月更文挑战第15天】Hibernate是开源ORM框架,将Java对象与数据库表映射,简化对象-关系映射,提升开发效率和性能。它自动化处理数据操作,支持多种数据库,自动生成SQL,提供配置选项和高级特性,减少手动SQL编写,便于切换数据库。
26 2
|
1天前
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
53 0
|
1天前
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
37 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 Java
Hibernate框架【四】——基本映射——多对一和一对多映射
Hibernate框架【四】——基本映射——多对一和一对多映射
108 0