Hibernate学习笔记(五)——多对多映射

这篇博客详细介绍了Hibernate中的多对多映射概念,包括其基本原理和一个具体的映射实例,帮助读者掌握如何在Java应用中实现数据库多对多关系的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、多对多映射的简单介绍

在之前的文章里,我们介绍了Hibernate中怎样使用一对一映射、一对多和多对一映射,现在来简单介绍一下多对多映射。多对多映射在数据库中也是很常见的一种映射关系,例如项目和员工之间就是很典型的多对多映射,一个项目中可能会涉及很多员工,同时一个员工也可能参与很多项目。在数据库中,要实现多对多映射,一种很常见的方法就是添加一个中间表来指定关联关系,即新增一张包含关联双方主键的关联表。而在Hibernate中可以通过在双方实体类中定义关联对象集合,并在双方的映射文件中配置<set>和<many-to-many>元素来实现多对多映射。下面就通过一个实例来分析以下Hibernate中的多对多映射。

二、多对多映射实例

我们就以项目和员工表作为实例来讲解多对多关系映射,首先我们要建立项目表project:
CREATE TABLE `project` (
  `proid` int(11) NOT NULL,
  `proname` varchar(20) NOT NULL,
  PRIMARY KEY (`proid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
项目表中只有两个简单的字段项目id和项目名称。然后我们建立员工表employee:
CREATE TABLE `employee` (
  `empid` int(11) NOT NULL,
  `empname` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`empid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表中有员工id和员工名称字段。因为项目和员工是多对多的映射关系,所以我们需要建立一张中间表proemp来表示它们的关联关系,这个表中有项目表和员工表的双方主键。
CREATE TABLE `proemp` (
  `rproid` int(11) DEFAULT NULL,
  `rempid` int(11) DEFAULT NULL,
  KEY `fk_rproid` (`rproid`),
  KEY `fk_rempid` (`rempid`),
  CONSTRAINT `fk_rempid` FOREIGN KEY (`rempid`) REFERENCES `employee` (`empid`),
  CONSTRAINT `fk_rproid` FOREIGN KEY (`rproid`) REFERENCES `project` (`proid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
建立好表之后我们就可以创建两个表对应的实体类了,要实现多对多关系,我们需要在两个实体类中分别定义对方的集合,首先我们建立项目类Project。
package com.imooc.entity;

import java.util.HashSet;
import java.util.Set;

public class Project {

	private int proid;
	
	private String proname;
	
	private Set<Employee> employees = new HashSet<Employee>();

	public int getProid() {
		return proid;
	}

	public void setProid(int proid) {
		this.proid = proid;
	}

	public String getProname() {
		return proname;
	}

	public void setProname(String proname) {
		this.proname = proname;
	}

	public Set<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}

	public Project() {
		super();
	}

	public Project(int proid, String proname) {
		super();
		this.proid = proid;
		this.proname = proname;
	}
}
然后我们定义员工类Employee:
package com.imooc.entity;

import java.util.HashSet;
import java.util.Set;

public class Employee {

	private int empid;
	
	private String empname;
	
	private Set<Project> projects = new HashSet<Project>();

	public int getEmpid() {
		return empid;
	}

	public void setEmpid(int empid) {
		this.empid = empid;
	}

	public String getEmpname() {
		return empname;
	}

	public void setEmpname(String empname) {
		this.empname = empname;
	}

	public Set<Project> getProjects() {
		return projects;
	}

	public void setProjects(Set<Project> projects) {
		this.projects = projects;
	}

	public Employee() {
		super();
	}

	public Employee(int empid, String empname) {
		super();
		this.empid = empid;
		this.empname = empname;
	}
	
}
实体类定义完成后就可以创建映射文件了,我们首先创建Project.hbm.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">
<!-- Generated 2016-10-5 10:14:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.imooc.entity.Project" table="project">
        <id name="proid" type="int">
            <column name="proid" />
            <generator class="assigned" />
        </id>
        <property name="proname" type="java.lang.String">
            <column name="proname" />
        </property>
        <!-- 实现多对多的映射关系 -->
        <set name="employees" table="proemp" cascade="all">
            <key>
                <column name="rproid" />
            </key>
            <many-to-many class="com.imooc.entity.Employee" column="rempid"/>
        </set>
    </class>
</hibernate-mapping>
在这个映射文件中,我们使用<set>元素和<many-to-many>元素实现多对多的映射关系,其中table属性指定了中间表proemp,而key和many-to-many的column都指定了在中间表中关联的外键名称。我们还在使用set元素中使用cascade属性来表示级联操作,这在之前的文章中也有介绍。接下来我们就可以创建Employee.hbm.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">
<!-- Generated 2016-10-5 10:14:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.imooc.entity.Employee" table="employee">
        <id name="empid" type="int">
            <column name="empid" />
            <generator class="assigned" />
        </id>
        <property name="empname" type="java.lang.String">
            <column name="empname" />
        </property>
        <set name="projects" table="proemp" inverse="true">
            <key>
                <column name="rempid" />
            </key>
            <many-to-many class="com.imooc.entity.Project" column="rproid"/>
        </set>
    </class>
</hibernate-mapping>
在这个映射文件里与Project.hbm.xml配置类似,只是我们使用inverse属性指定了控制权由Project来控制。配置好映射文件后我们需要在hibernate.cfg.xml文件中进行注册,在这里就不赘述了,之前也有介绍过。最后我们使用JUnit来进行测试,创建SessionFactory、Session和Transaction的过程就不介绍了,与之前的方法相同,我们直接看测试方法。
	@Test
	public void testAdd() {
		Project project1 = new Project(1001, "项目一");
		Project project2 = new Project(1002, "项目二");
		
		Employee employee1 = new Employee(1, "张三");
		Employee employee2 = new Employee(2, "李四");
		
		project1.getEmployees().add(employee1);
		project1.getEmployees().add(employee2);
		
		project2.getEmployees().add(employee1);
		
		session.save(project1);
		session.save(project2);
	}
我们在这个方法里创建了两个项目和两个员工,并分别对两个项目关联不同的员工,执行插入操作后观察数据库表,我们会发现插入项目表和员工表数据成功了,同时插入中间表表示项目和员工关联关系的表也成功了。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值