Hibernate之关联关系映射(一对多和多对一映射,多对多映射)
分类:
IT文章
•
2022-04-16 10:11:43
~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习一下框架了,不然又被忽悠让去培训。)~~~
1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射:
1.1:一对多和多对一映射,举例说明:
学生和老师:
一个老师可以教多个学生 【一对多映射】
多个学生可以被一个老师教【多对一映射】
部门与员工:
一个部门有多个员工【一对多映射】
多个员工属于一个部门【多对一映射】
1.2:多对多,举例说明:
项目和开发员工:【双向一对多即多对多映射】
一个项目有多个开发人员【一对多】
一个开发人员参与多个项目【一对多】
2:一对多和多对一映射,理清以下思路就可以进行简单的开发了:
2.1:首先导入hibernate框架所需要的包哦~~~
2.2:由于是在hibernate.cfg.xml配置里面自动生成数据库和表,所以不用手动创建了
2.3:进入正题,开发创建实体类;下面是两个实体类的关键点;
Dept.java:
注意private Set<Employee> emps;//部门对应多个员工,即一对多的关系
Employee.java:
private Dept dept;//员工和部门的关系
1 package com.bie.po;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 /**
7 * @author BieHongLi
8 * @version 创建时间:2017年3月20日 上午9:45:21
9 * 部门的实体类
10 * 关键点,是通过部门实体类维护到员工的实体类
11 */
12 public class Dept {
13
14 private int deptId;//部门编号
15 private String deptName;//部门名称
16
17 private Set<Employee> emps;//部门对应多个员工,即一对多的关系
18 //private Set<Employee> emps = new HashSet<>();//方便赋值,这里可以直接创建实例化
19
20
21 public int getDeptId() {
22 return deptId;
23 }
24 public void setDeptId(int deptId) {
25 this.deptId = deptId;
26 }
27 public String getDeptName() {
28 return deptName;
29 }
30 public void setDeptName(String deptName) {
31 this.deptName = deptName;
32 }
33 public Set<Employee> getEmps() {
34 return emps;
35 }
36 public void setEmps(Set<Employee> emps) {
37 this.emps = emps;
38 }
39
40
41 }
View Code
1 package com.bie.po;
2 /**
3 * @author BieHongLi
4 * @version 创建时间:2017年3月20日 上午9:46:45
5 * 员工的实体类
6 */
7 public class Employee {
8
9 private int empId;//员工的编号
10 private String empName;//员工的名称
11 private double salary;//员工的薪资
12
13 private Dept dept;//员工和部门的关系
14
15 public int getEmpId() {
16 return empId;
17 }
18 public void setEmpId(int empId) {
19 this.empId = empId;
20 }
21 public String getEmpName() {
22 return empName;
23 }
24 public void setEmpName(String empName) {
25 this.empName = empName;
26 }
27 public double getSalary() {
28 return salary;
29 }
30 public void setSalary(double salary) {
31 this.salary = salary;
32 }
33 public Dept getDept() {
34 return dept;
35 }
36 public void setDept(Dept dept) {
37 this.dept = dept;
38 }
39
40
41 }
View Code
2.4:创建好实体类就可以进行创建hibernate的映射文件了,如Dept.hbm.xml和Employee.hbm.xml映射文件;
部门表进行映射的时候:
需要注意使用set集合进行映射的注意点:
Dept映射关键点:
1:指定映射的集合属性:"emps"
2:集合属性对应的集合表:"20171021_employee"
3:集合表的外键字段"20171021_employee.deptId"
4:集合元素的类型
员工表进行映射的时候:
需要注意<many-to-one name="dept" column="deptId" class="Dept"></many-to-one>
将一个对象映射成为外键字段,只能使用many-to-one这个配置。
Employee映射关键点:
1:映射的部门属性:dept
2:映射的部门对象,对应的外键字段:dept_id
3:指定部门的类型
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
5
6 <!-- 如果hibernate-mapping的package属性直接初始化了,下面就可以直接引用了 -->
7 <hibernate-mapping package="com.bie.po">
8 <class name="Dept" table="dept">
9 <!-- 第一首先写主键映射 -->
10 <id name="deptId" column="deptId">
11 <generator class="native"></generator>
12 </id>
13 <!-- 第二写非主键映射 -->
14 <property name="deptName" column="deptName" length="20" type="string"></property>
15
16 <!--
17 第三写其他映射,比如这里的set集合映射,
18 -->
19 <!--
20 一对多关联映射配置(通过部门管理到员工)
21 Dept映射关键点
22 (1)指定映射的集合属性:""emps;
23 (2)集合属性对应的集合表:"employee";
24 (3)集合表的外键字段:employee.empId
25 (4)集合元素的类型
26 -->
27 <!-- name指定了映射的集合的属性,即集合实例化的emps;table指定了集合属性对应的集合表 -->
28 <set name="emps" table="employee">
29 <!--column指定了集合表的外键 -->
30 <key column="deptId"></key>
31 <!-- class由于上面已经写了包名,这里直接使用即可 -->
32 <one-to-many class="Employee"/>
33 </set>
34 </class>
35 </hibernate-mapping>
36
37
38
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
5 <!-- 这里指定package,里面就可以直接引用了 -->
6 <hibernate-mapping package="com.bie.po">
7 <class name="Employee" table="employee">
8 <!-- 1:主键映射 -->
9 <id name="empId" column="empId">
10 <generator class="native"></generator>
11 </id>
12
13 <!-- 2:非主键映射 -->
14 <property name="empName" column="empName" length="20" type="string"></property>
15 <property name="salary" column="salary" type="double"></property>
16
17 <!--
18 多对一的映射配置;Employee映射的关键点
19 (1)映射的部门属性:dept
20 (2)映射的部门对新,对应的外键字段:deptId
21 (3)部门的类型:Dept
22 -->
23 <many-to-one name="dept" column="deptId" class="Dept"></many-to-one>
24 </class>
25
26 </hibernate-mapping>
27
28
2.5:配置好映射文件,就可以配置hibernate的配置文件了,hibernate.cfg.xml;
注意:
第二部分其他配置的时候注意显示sql语句和方言还有自动创建数据表这些细节问题
第三部分加载映射文件的写法也需要注意
1 <!DOCTYPE hibernate-configuration PUBLIC
2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
3 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
4
5 <hibernate-configuration>
6 <session-factory>
7 <!-- 第一部分:连接数据库的操作,加载驱动,连接数据库的url和账号密码 -->
8 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
9 <property name="hibernate.connection.url">jdbc:mysql:///test</property>
10 <property name="hibernate.connection.username">root</property>
11 <property name="hibernate.connection.password">123456</property>
12
13 <!-- 第二部分:其他相关配置 -->
14 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
15 <property name="hibernate.show_sql">true</property>
16 <property name="hibernate.format_sql">true</property>
17 <property name="hibernate.hbm2ddl.auto">update</property>
18 <!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
19
20 <!-- 第三部分:加载映射文件 -->
21 <mapping resource="com/bie/po/Dept.hbm.xml"/>
22 <mapping resource="com/bie/po/Employee.hbm.xml"/>
23 </session-factory>
24 </hibernate-configuration>
2.6:最后就可以使用junit进行测试了,如下所示:
(1)首先清楚下面两种测试的区别是是否在实体类实例化set集合
private Set<Employee> emps;//部门对应多个员工,即一对多的关系
private Set<Employee> emps = new HashSet<>();//方便赋值,这里可以直接创建实例化
(2)下面两种情况都可以设置好部门和员工的信息。就是在配置映射的时候一定搞清楚set集合映射的配置和many-to-one的配置
I:从部门的一方设置员工的信息【不推荐】
dept.getEmps().add(emp1);
dept.getEmps().add(emp2);
II:从员工的一方设置好部门的信息【推荐,在一对多和多对一的关联关系中,保存数据最好是通过多对一来维护关系,这样可以减少update语句的生成,从而提高hibernate的利用效率】
emp1.setDept(dept);
emp2.setDept(dept);
(3)最后是保存的顺序,保存的顺序最好是先保存一的一方再保存多的一方,这样可以提高效率,少执行sql语句
第一种方法(推荐)
session.save(dept);//先保存一的一方
session.save(emp1);
session.save(emp2);//再保存多的一方,关系会自动维护(但是映射配置必须配置好的 )
第二种方法(不推荐)
session.save(emp1);//先保存多的一方,关系会自动维护(但是映射配置必须配置好的 )
session.save(emp2);
session.save(dept);//再保存一的一方
1 package com.bie.test;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 import org.hibernate.Session;
7 import org.hibernate.SessionFactory;
8 import org.hibernate.cfg.Configuration;
9 import org.junit.Test;
10
11 import com.bie.po.Dept;
12 import com.bie.po.Employee;
13
14 /**
15 * @author BieHongLi
16 * @version 创建时间:2017年3月20日 上午10:29:38
17 *
18 */
19 public class OneManyTest {
20
21 //初始化静态的session工厂
22 private static SessionFactory sf = null;
23 static{
24 //这里使用简写的方法,首先加载默认的hibernate.cfg.xml,然后是创建session工厂
25 sf = new Configuration().configure().buildSessionFactory();
26 }
27
28 @Test
29 public void test(){
30 //创建session,import org.hibernate.Session;
31 Session session = sf.openSession();
32 //session开始事务
33 session.beginTransaction();
34
35 //1:关键点,部门对象的初始化,创建一个部门
36 Dept dept = new Dept();
37 dept.setDeptName("开发部");
38
39 //2:关键点,员工的初始化,创建两个人对象
40 Employee emp1 = new Employee();
41 emp1.setEmpName("张三");
42 Employee emp2 = new Employee();
43 emp2.setEmpName("李四");
44
45 //3:然后将创建的人添加到set集合中
46 Set<Employee> set = new HashSet<>();
47 set.add(emp1);
48 set.add(emp2);
49
50 //4:再将set集合中保存的人保存到部门里面
51 dept.setEmps(set);
52
53 //5:最后保存员工对象,部门
54 session.save(emp1);
55 session.save(emp2);
56 session.save(dept);
57
58 //提交事务,省去了事务new实例化了
59 session.getTransaction().commit();
60 //关闭session
61 session.close();
62 }
63
64 @Test
65 public void test2(){
66 //创建session,import org.hibernate.Session;
67 Session session = sf.openSession();
68 //session开始事务
69 session.beginTransaction();
70
71 //1:关键点,部门对象的初始化,创建一个部门
72 Dept dept = new Dept();
73 dept.setDeptName("研发部2");
74
75 //2:关键点,员工的初始化,创建两个人对象
76 Employee emp1 = new Employee();
77 emp1.setEmpName("小三子2");
78 Employee emp2 = new Employee();
79 emp2.setEmpName("小四子2");
80
81 //3:再将set集合中保存的人保存到部门里面
82 //dept.getEmps().add(emp1);
83 //dept.getEmps().add(emp2);
84
85 //或者是从员工的一方设置好部门的信息
86 emp1.setDept(dept);
87 emp2.setDept(dept);
88
89 //4:最后保存员工对象,部门,保存的顺序也会影响sql语句的,所以最好先保存一的一方
90 session.save(dept);//先保存一的一方
91 session.save(emp1);
92 session.save(emp2);//再保存多的一方,关系会自动维护(但是映射配置必须配置好的 )
93
94 //提交事务,省去了事务new实例化了
95 session.getTransaction().commit();
96 //关闭session
97 session.close();
98 }
99
100 }
测试结果如下所示(由于set集合在实体类里面初始化和不初始化出现下面两种情况,所以需要注意两种测试测试的方法):

3:多对多映射,这个需要理解清楚他们之间的关系。不然很容易搞混乱的。
3.1:创建实体类:
Project.java
项目下面的多个员工
private Set<Develope> deve = new HashSet<Develope>();
Develope.java
开发人员参入的多个项目
private Set<Project> project = new HashSet<Project>();
1 package com.bie.domain;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 /**
7 * @author BieHongLi
8 * @version 创建时间:2017年3月20日 下午5:32:42
9 * 项目的实体类
10 */
11 public class Project {
12
13 private int proId;
14 private String proName;
15
16 //项目下面的多个员工
17 private Set<Develope> deve = new HashSet<Develope>();
18
19 public int getProId() {
20 return proId;
21 }
22 public void setProId(int proId) {
23 this.proId = proId;
24 }
25 public String getProName() {
26 return proName;
27 }
28 public void setProName(String proName) {
29 this.proName = proName;
30 }
31 public Set<Develope> getDeve() {
32 return deve;
33 }
34 public void setDeve(Set<Develope> deve) {
35 this.deve = deve;
36 }
37
38 }
View Code