Hibernate框架进阶(中篇)之多表关系

导读

Hibernate进阶主要分为上中下三篇,本文是中篇,主要讲解Hibernate框架中多表关系的实现。我们知道多表关系有一对一、一对多(多对一)和多对多三种关系。而1对1关系一般合并为一个表处理,所以本文主要讲解1对多和多对多关系的实现。

一、一对多关系

一对多的关系很多,比如人和籍贯就是一对多的关系,下面就用人和籍贯这个实例来展开说明。

1、数据库的实现

对于一对多关系的建立,我们通常是使用外键(foreign key)来表示。外键列添加在一对多的“多”这一方。这里用person表和province表分别表示人和籍贯,所以这个外键就加入province表中,值就是person表的主键值。

2、实体类的实现

对应数据库表,实体类分别用Person类和Province类表示。而在实体类中就没有外键这种概念了。

对于Person类是“多对一”,即很多人属于同一个省份。所以怎么在Person类中表示所属的这一个省份呢?使用类Province即可。

反过来对于Province类是“一对多”,即一个省份有很多人。那么怎么表示很多人呢?即很多Person类,所以我们很快想到使用集合来保存Person类,这里我们使用Set集合。(Set集合值不会重复更符合实际的需求)。

所以,最终的类实现如下:

 1 package domain;
 2
 3 public class Person {
 4     private Long per_id;//省份证
 5     private String name;//姓名
 6     private Integer age;//年龄
 7
 8     //关系
 9     private Province province;//所属省份
10
11     public Long getPer_id() {
12         return per_id;
13     }
14
15     public void setPer_id(Long per_id) {
16         this.per_id = per_id;
17     }
18
19     public String getName() {
20         return name;
21     }
22
23     public void setName(String name) {
24         this.name = name;
25     }
26
27     public Integer getAge() {
28         return age;
29     }
30
31     public void setAge(Integer age) {
32         this.age = age;
33     }
34
35     public Province getProvince() {
36         return province;
37     }
38
39     public void setProvince(Province province) {
40         this.province = province;
41     }
42
43     @Override
44     public String toString() {
45         return "Person [per_id=" + per_id + ", name=" + name + ", age=" + age + ", province=" + province + "]";
46     }
47 }

Person

 1 package domain;
 2
 3 import java.util.HashSet;
 4 import java.util.Set;
 5
 6 public class Province {
 7     private Long pro_id;//省代码
 8     private String name;//省名
 9
10     //关系
11     private Set<Person> personSet = new HashSet<Person>();//省份的人口集合
12
13     public Long getPro_id() {
14         return pro_id;
15     }
16
17     public void setPro_id(Long pro_id) {
18         this.pro_id = pro_id;
19     }
20
21     public String getName() {
22         return name;
23     }
24
25     public void setName(String name) {
26         this.name = name;
27     }
28
29     public Set<Person> getPersonSet() {
30         return personSet;
31     }
32
33     public void setPersonSet(Set<Person> personSet) {
34         this.personSet = personSet;
35     }
36     @Override
37     public String toString() {
38         return "Province [pro_id=" + pro_id + ", name=" + name + ", personSet=" + personSet + "]";
39     }
40 }

Province

3、数据库表和实体类的映射关系

配置文件主要是orm元数据(映射关系)和主配置文件的配置。

3.1、orm元数据的配置

orm元数据的配置和之前的配置几乎一致,主要是如何在配置文件中表示外键。具体看下面的配置方法:

 1 <?xml version="1.0" encoding="UTF-8"?>
 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="domain" >
 7
 8     <class name="Person" table="person" >
 9         <id name="per_id"  >
10             <generator class="identity"></generator>
11         </id>
12
13     <property name="name" column="name" ></property>
14     <property name="age" column="age" ></property>
15
16     <!-- 多对一关系的配置: -->
17     <many-to-one name="province" column="pro_id" class="Province" ></many-to-one>
18
19     </class>
20 </hibernate-mapping>

Person.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 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="domain" >
 7
 8     <class name="Province" table="province" >
 9         <id name="pro_id"  >
10             <generator class="identity"></generator>
11         </id>
12
13     <property name="name" column="name" ></property>
14
15     <!-- 一对多关系的配置: -->
16     <set name="personSet">
17         <key column="pro_id"></key>
18         <one-to-many class="Person"/>
19     </set>
20
21     </class>
22 </hibernate-mapping>

Province.hbm.xml

总结:

多对一:

一对多:

3.2、主配置文件的配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!-- 导入约束 -->
 3 <!DOCTYPE hibernate-configuration PUBLIC
 4     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 5     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 6 <!-- 主配置文件 -->
 7 <hibernate-configuration>
 8     <session-factory>
 9         <!--
10         #hibernate.dialect org.hibernate.dialect.MySQLDialect
11         #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
12         #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
13         #hibernate.connection.driver_class com.mysql.jdbc.Driver
14         #hibernate.connection.url jdbc:mysql:///test
15         #hibernate.connection.username gavin
16         #hibernate.connection.password
17          -->
18          <!-- 数据库驱动 -->
19         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
20          <!-- 数据库url -->
21         <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
22          <!-- 数据库连接用户名 -->
23         <property name="hibernate.connection.username">root</property>
24          <!-- 数据库连接密码 -->
25         <property name="hibernate.connection.password">password</property>
26         <!-- 数据库方言 -->
27         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
28
29         <property name="hibernate.current_session_context_class">thread</property>
30         <property name="hibernate.show_sql">true</property>
31         <property name="hibernate.format_sql">true</property>
32         <property name="hibernate.hbm2ddl.auto">update</property>
33
34         <!-- 引入orm元数据-->
35         <mapping resource="domain/Person.hbm.xml" />
36         <mapping resource="domain/Province.hbm.xml" />
37
38     </session-factory>
39 </hibernate-configuration>

hibernate.cfg.xml

4、Hibernate代码测试

 1 package Test;
 2
 3 import org.hibernate.Session;
 4 import org.hibernate.Transaction;
 5 import org.junit.Test;
 6
 7 import domain.Person;
 8 import domain.Province;
 9 import utils.HibernateUtils;
10
11 public class Demo {
12
13     @Test
14     public void test(){
15         //1、创建对话session
16         Session session = HibernateUtils.openSession();
17         //2、开启事务
18         Transaction tx = session.beginTransaction();
19
20         //3、操作事务:假设张三和李四籍贯北京,现在讲数据持久化到数据库中
21         //---------------------------------
22         //创建实体对象
23         Province pro = new Province();
24         pro.setName("北京");
25         Person p1 = new Person();
26         Person p2 = new Person();
27         p1.setName("张三");
28         p2.setName("李四");
29
30         //建立对象之间的关系
31         //一对多:
32         pro.getPersonSet().add(p1);
33         pro.getPersonSet().add(p2);
34         //多对一
35         p1.setProvince(pro);
36         p2.setProvince(pro);
37
38         //将信息持久化到数据库
39         session.save(pro);
40         session.save(p1);
41         session.save(p2);
42
43         //----------------------------------
44
45         //4、提交事务
46         tx.commit();
47         //5、关闭资源
48         session.close();
49     }
50 }

测试结果:

5、扩展:cascade属性和reverse属性

1)cascade属性

cascade属性是配置级联操作的一个配置属性,cascade的属性值有:save-update(级联保存)、delete(级联删除)、all(级联保存和删除)。

级联的意思是当你配置了这个属性,那么你操作这个对象时对应的关系对象也会进行相应操作。比如我在上面的Province映射关系中配置了:

那么当我执行session.save(pro)时就不必再执行session.save(p1)和session.save(p2)。

结论:该属性是用来简化书写的,如果要使用,建议不要使用delete和all,因为级联删除存在很大风险,可能会无意中删除很多数据。

2)reverse属性

另一个属性reverse在一对多关系中可以用来优化性能。reverse有两个值:true和false。当选择true是表示放弃维护外键,默认是false。(这个属性在多对多关系中必须使用,因为不能使用两个表来同时维护外键)。

二、多对多关系

1、数据库的实现

多对多的关系是通过转换为两个一对多来实现的。例如学生选课这个关系,一个学生可以选多门课,每个课程又可以对应很多学生,即多对多关系。这样我们就可以在student表和course表之间增加一个关系表choose表(选课表),用来存储学生id和课程id,以此来建立对应关系。这样多对多的关系就变成了两个一对多的关系。

2、实体类的实现

实体类的创建和一对多是一样的道理。

 1 package domain;
 2
 3 import java.util.HashSet;
 4 import java.util.Set;
 5
 6 public class Student {
 7     private Long sid;//学号
 8     private String sname;//姓名
 9
10     private Set<Course> courseSet = new HashSet<Course>();//选课信息
11
12     public Long getSid() {
13         return sid;
14     }
15
16     public void setSid(Long sid) {
17         this.sid = sid;
18     }
19
20     public String getSname() {
21         return sname;
22     }
23
24     public void setSname(String sname) {
25         this.sname = sname;
26     }
27
28     public Set<Course> getCourseSet() {
29         return courseSet;
30     }
31
32     public void setCourseSet(Set<Course> courseSet) {
33         this.courseSet = courseSet;
34     }
35
36 }

Student

 1 package domain;
 2
 3 import java.util.HashSet;
 4 import java.util.Set;
 5
 6 public class Course {
 7     private Long cid;//课程代码
 8     private String cname;//课程名
 9
10     private Set<Student> studentSet = new HashSet<Student>();//学生信息
11
12     public Long getCid() {
13         return cid;
14     }
15
16     public void setCid(Long cid) {
17         this.cid = cid;
18     }
19
20     public String getCname() {
21         return cname;
22     }
23
24     public void setCname(String cname) {
25         this.cname = cname;
26     }
27
28     public Set<Student> getStudentSet() {
29         return studentSet;
30     }
31
32     public void setStudentSet(Set<Student> studentSet) {
33         this.studentSet = studentSet;
34     }
35
36 }

Course

3、数据库表和实体类的映射关系

这里的配置和之前的配置也是几乎不变,关键在于多对多关系的配置。

 1 <?xml version="1.0" encoding="UTF-8"?>
 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="domain" >
 7
 8     <class name="Student" table="student" >
 9         <id name="sid"  >
10             <generator class="identity"></generator>
11         </id>
12
13     <property name="sname" column="sname" ></property>
14
15     <!-- 多对多关系的配置: -->
16     <set name="courseSet" table="choose" >
17         <key column="sid"></key>
18         <many-to-many class="Course" column="cid"></many-to-many>
19     </set>
20
21     </class>
22 </hibernate-mapping>

Student.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 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="domain" >
 7
 8     <class name="Course" table="course" >
 9         <id name="cid"  >
10             <generator class="identity"></generator>
11         </id>
12
13     <property name="cname" column="cname" ></property>
14
15     <!-- 多对多关系的配置: -->
16     <set name="studentSet" table="choose" inverse="true">
17         <key column="cid"></key>
18         <many-to-many class="Student" column="sid"></many-to-many>
19     </set>
20
21     </class>
22 </hibernate-mapping>

Course.hbm.xml

变化:

Student.hbm.xml中

Course.hbm.xml中

主配置文件中:

5、测试

package Test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import domain.Course;
import domain.Student;
import utils.HibernateUtils;

public class Demo2 {
    @Test
    public void test(){
        //1、创建对话session
        Session session = HibernateUtils.openSession();
        //2、开启事务
        Transaction tx = session.beginTransaction();

        //3、操作事务:假设有语数外三门课,张三选了语文和数学,李四选了语文和英语,Tom选了数学。将上述信息持久化到数据库
        //---------------------------------
        //创建实体对象
        Course c1 = new Course();
        c1.setCname("语文");
        Course c2 = new Course();
        c2.setCname("数学");
        Course c3 = new Course();
        c3.setCname("英语");

        Student s1 = new Student();
        s1.setSname("张三");
        Student s2 = new Student();
        s2.setSname("李四");
        Student s3 = new Student();
        s3.setSname("Tom");

        //建立对象之间的关系
        //课程对应学生
        c1.getStudentSet().add(s1);
        c1.getStudentSet().add(s2);
        c2.getStudentSet().add(s2);
        c2.getStudentSet().add(s3);
        c3.getStudentSet().add(s2);

        //学生对应课程
        s1.getCourseSet().add(c1);
        s1.getCourseSet().add(c2);
        s2.getCourseSet().add(c2);
        s2.getCourseSet().add(c3);
        s3.getCourseSet().add(c2);

        //将信息持久化到数据库
        session.save(c1);
        session.save(c2);
        session.save(c3);
        session.save(s1);
        session.save(s2);
        session.save(s3);
        //----------------------------------

        //4、提交事务
        tx.commit();
        //5、关闭资源
        session.close();
    }
}

测试结果:

时间: 2024-07-31 18:13:21

Hibernate框架进阶(中篇)之多表关系的相关文章

Hibernate框架单向多对一关联映射关系

建立多对一的单向关联关系    Emp.java            private Integer empNo //员工编号            private String empName //员工姓名            //private Integer deptNo;  //部门编号            private Dept dept;    //所属部门    Dept.java            private Byte deptNo;              

Hibernate框架简介

面试被问及了Hibernate框架,虽然问的很少,很简单,但是还是简单的总结一下吧,以备以后不时之需. 什么是Hibernate框架? 百科定义:Hibernate框架式一个开源的对象关系映射(ORM)框架,是对JDBC的轻量级的对象封装,使java程序员可以使用对象思维来操纵DB. 白话版:在Hibernate之前,我们是如何操作DB的?JDBC,需要在程序中嵌入SQL语句.效率低下,不能忍啊.但是Hibernate的出现,让我们无需再操纵SQL语句了,每个表实例被实例化为一个java对象,操

hibernate 表关系映射详解之一对多

一对多 传统模式:jdbc连接数据库的传统模式下,是通过主键连接外键实现一对多关系的映射, 其数据库中表的对应关系是在多方加入一方的主键,而后形成外键连接. Hibernate:引入hibernate框架后,通过类的形式来表示一对多的关系. 举例:订单与订单详细的关系,一个订单包含多个商品,多个商品属于一个订单,两者的关系是一对多的关系. 实现原理: 面向对象实现------ 在order类中加入item类的set集合 ,表示在订单类中包含有多个订单详细(集合表示). 层次结构: 步骤一:编写实

Hibernate多表关系

Hibernate多表关系 hibernate 一对多(多对一) 创建实体 配置ORM映射文件 创建测试文件 双方关系维护 级联操作 外键的维护权管理 双方关系维护.级联操作.外键维护权之间的关系 一对多(多对一) 在一个视频管理的系统中应该包含这样两个表讲课人Speaker.视频Video.其中一个讲课人可以讲多个视频,而一个视频只能属于一个讲课人:在这里Speaker就是一的状态,Video就是多的状态. 创建实体 在Speaker中添加set集合(如果添加list集合需要在配置文件中额外配

Hibernate多对一,多对多的表映射关系

版权声明:本文为博主原创文章,未经博主允许不得转载. 本文旨在介绍hibernate的实体与数据库表的各种关系映射 1.多对一/一对多关系映射 User-------用户表 Department -------------部门表 Contact---------------组件部分,(地址类)) 下面开始各实体代码: User.java实体类 package com.huangchao.model; import java.io.Serializable; import java.util.Da

ORM进阶:Hibernate框架搭建及开发

本节将开始,使用hibernate搭建持久层.当然在决定用不用之前,还请斟酌一下是否使用.了解一下Hibernate的优缺点. Hibernate优劣对比 Hibernate是一个持久的ORM框架,首先要简历一个Java Project  这个就不用多说了吧.之后,我们来搭建Hibernate框架. 第一步:引入相关Jar包.包含两部分,核心jar包(Hibernate_Home/hibernate3.jar)和相关包(Hibernate_Home/lib/*.jar) 如上图. 如果没有,请去

Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理

Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理 本博文主要介绍 Laravel 框架中 Eloquent  对一对多关系的处理,在 Laravel Administrator(后台扩展包) 您的数据库可能是彼此相关的.比如,一篇博客文章可能有许多评论,或者一个订单与下订单的用户相关.Eloquent 使得管理和处理这些关系变得简单.Laravel 提供了四种类型的关系: -一对一 -一对多 - 多对多 - 多态关系 一对多 一个一对多关系的例子是一篇博客文章有许多评

六 Hibernate表关系及其配置

Hibernate的一对多关联映射 Hibernate的多对多关联映射 数据库表与表之间的关系:一对多,多对多,一对一 一对多:一个部门对应多个员工,一个员工只能属于一个部门.一个客户对应多个联系人,一个联系人只能属于一个客户 一对多建表:在多的一方创建外键. 多对多:一个学生可以选择多门课程,一门课程可以被多个学生选择.一个用户可以选择多个角色,一个角色可以被多个用户选择. 多对多建表:创建中间表.中间表至少有两个字段分别作为外键指向多对多双方的主键. 一对一(了解): 一般可以建成一张表.

Hibernate框架之路(二)一对多关系

在下列案例中: 客户是一:联系人是多:客户可以拥有多个联系人:一个联系人只有一个客户 1.编写实体类 package com.pojo; import java.util.HashSet; import java.util.Set; public class User { private Integer uId; //客户ID(主表) 客户是一 private String uName; //名字 private String uTel; //手机 // 在客户的表中显示多个联系人 // 使用s