导读

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

一、一对多关系

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

1、数据库的实现

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

2、实体类的实现

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

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

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

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

 package domain;

 public class Person {
private Long per_id;//省份证
private String name;//姓名
private Integer age;//年龄 //关系
private Province province;//所属省份 public Long getPer_id() {
return per_id;
} public void setPer_id(Long per_id) {
this.per_id = per_id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Province getProvince() {
return province;
} public void setProvince(Province province) {
this.province = province;
} @Override
public String toString() {
return "Person [per_id=" + per_id + ", name=" + name + ", age=" + age + ", province=" + province + "]";
}
}

Person

 package domain;

 import java.util.HashSet;
import java.util.Set; public class Province {
private Long pro_id;//省代码
private String name;//省名 //关系
private Set<Person> personSet = new HashSet<Person>();//省份的人口集合 public Long getPro_id() {
return pro_id;
} public void setPro_id(Long pro_id) {
this.pro_id = pro_id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<Person> getPersonSet() {
return personSet;
} public void setPersonSet(Set<Person> personSet) {
this.personSet = personSet;
}
@Override
public String toString() {
return "Province [pro_id=" + pro_id + ", name=" + name + ", personSet=" + personSet + "]";
}
}

Province

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

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

3.1、orm元数据的配置

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

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="domain" > <class name="Person" table="person" >
<id name="per_id" >
<generator class="identity"></generator>
</id> <property name="name" column="name" ></property>
<property name="age" column="age" ></property> <!-- 多对一关系的配置: -->
<many-to-one name="province" column="pro_id" class="Province" ></many-to-one> </class>
</hibernate-mapping>

Person.hbm.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="domain" > <class name="Province" table="province" >
<id name="pro_id" >
<generator class="identity"></generator>
</id> <property name="name" column="name" ></property> <!-- 一对多关系的配置: -->
<set name="personSet">
<key column="pro_id"></key>
<one-to-many class="Person"/>
</set> </class>
</hibernate-mapping>

Province.hbm.xml

总结:

多对一:

一对多:

3.2、主配置文件的配置

 <?xml version="1.0" encoding="UTF-8"?>
<!-- 导入约束 -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- 主配置文件 -->
<hibernate-configuration>
<session-factory>
<!--
#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password
-->
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<!-- 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">password</property>
<!-- 数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property> <!-- 引入orm元数据-->
<mapping resource="domain/Person.hbm.xml" />
<mapping resource="domain/Province.hbm.xml" /> </session-factory>
</hibernate-configuration>

hibernate.cfg.xml

4、Hibernate代码测试

 package Test;

 import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import domain.Person;
import domain.Province;
import utils.HibernateUtils; public class Demo { @Test
public void test(){
//1、创建对话session
Session session = HibernateUtils.openSession();
//2、开启事务
Transaction tx = session.beginTransaction(); //3、操作事务:假设张三和李四籍贯北京,现在讲数据持久化到数据库中
//---------------------------------
//创建实体对象
Province pro = new Province();
pro.setName("北京");
Person p1 = new Person();
Person p2 = new Person();
p1.setName("张三");
p2.setName("李四"); //建立对象之间的关系
//一对多:
pro.getPersonSet().add(p1);
pro.getPersonSet().add(p2);
//多对一
p1.setProvince(pro);
p2.setProvince(pro); //将信息持久化到数据库
session.save(pro);
session.save(p1);
session.save(p2); //---------------------------------- //4、提交事务
tx.commit();
//5、关闭资源
session.close();
}
}

测试结果:

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、实体类的实现

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

 package domain;

 import java.util.HashSet;
import java.util.Set; public class Student {
private Long sid;//学号
private String sname;//姓名 private Set<Course> courseSet = new HashSet<Course>();//选课信息 public Long getSid() {
return sid;
} public void setSid(Long sid) {
this.sid = sid;
} public String getSname() {
return sname;
} public void setSname(String sname) {
this.sname = sname;
} public Set<Course> getCourseSet() {
return courseSet;
} public void setCourseSet(Set<Course> courseSet) {
this.courseSet = courseSet;
} }

Student

 package domain;

 import java.util.HashSet;
import java.util.Set; public class Course {
private Long cid;//课程代码
private String cname;//课程名 private Set<Student> studentSet = new HashSet<Student>();//学生信息 public Long getCid() {
return cid;
} public void setCid(Long cid) {
this.cid = cid;
} public String getCname() {
return cname;
} public void setCname(String cname) {
this.cname = cname;
} public Set<Student> getStudentSet() {
return studentSet;
} public void setStudentSet(Set<Student> studentSet) {
this.studentSet = studentSet;
} }

Course

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

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

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="domain" > <class name="Student" table="student" >
<id name="sid" >
<generator class="identity"></generator>
</id> <property name="sname" column="sname" ></property> <!-- 多对多关系的配置: -->
<set name="courseSet" table="choose" >
<key column="sid"></key>
<many-to-many class="Course" column="cid"></many-to-many>
</set> </class>
</hibernate-mapping>

Student.hbm.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="domain" > <class name="Course" table="course" >
<id name="cid" >
<generator class="identity"></generator>
</id> <property name="cname" column="cname" ></property> <!-- 多对多关系的配置: -->
<set name="studentSet" table="choose" inverse="true">
<key column="cid"></key>
<many-to-many class="Student" column="sid"></many-to-many>
</set> </class>
</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();
}
}

测试结果:

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

  1. Hibernate框架进阶(上篇)

    导读 前面一片文章介绍了Hibernate框架的入门,主要是讲解Hibernate的环境搭建和简单测试,有兴趣的童鞋出门左转.本文在入门的基础上进行Hibernate的进阶讲解,分为上中下三篇,本篇为 ...

  2. Hibernate框架进阶(下篇)之查询

    导读 Hibernate进阶篇分为上中下三篇,本文为最后一篇,主要内容是Hibernate框架的查询,主要包括hql语句查询,criteria查询以及查询策略的选择. 知识框架 Hibernate查询 ...

  3. JPA、Hibernate框架、通用mapper之间的关系及通用mapper的具体实现

    JPA是描述对象-关系表的映射关系,将运行期实体对象持久化到数据库中,提出以面向对象方式操作数据库的思想. Hibernate框架核心思想是ORM-实现自动的关系映射.缺点:由于关联操作提出Hql语法 ...

  4. Hibernate框架双向多对多关联映射关系

    建立双向多对多关联关系    Project.java (项目表)                private Integer proid;                private Strin ...

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

    建立多对一的单向关联关系    Emp.java            private Integer empNo //员工编号            private String empName / ...

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

    建立单向多对多关联关系    Project.java (项目表)                private Integer proid;                private Strin ...

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

    Php Laravel框架 多表关系处理 之 Eloquent一对多关系处理 本博文主要介绍 Laravel 框架中 Eloquent  对一对多关系的处理以及在 Laravel Administra ...

  8. Hibernate框架学习之注解配置关系映射

         上篇文章我们通过注解对映射了单个实体类,但是具体项目中往往实体类之间又是相互关联的,本篇文章就是从实体类之间存在的不同关联角度,具体学习下如何映射他们之间的关联,主要涉及内容如下: 单向的一 ...

  9. Hibernate框架笔记03表操作多对多配置

    目录 1. 数据库表与表之间的关系 1.1 一对多关系 1.2 多对多关系 1.3 一对一关系[了解] 2. Hibernate的一对多关联映射 2.1 创建一个项目,引入相关jar包 2.2. 创建 ...

随机推荐

  1. (转)linux下如何批量杀JAVA进程或某个进程方法

    在工作中经常需要停止JAVA进程,停止时间也比较长,那么有时候因为一些情况,需要把 linux 下JAVA所有进程 kill 掉,又不能用killall 直接杀掉某一进程名称包含的所有运行中进程(我们 ...

  2. Oil Deposits

    Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...

  3. visual filters 滤镜 ie

    滤镜ie9开始就废弃了,用来对ie4-8实现一些多媒体动画之类的效果.可以添加到标准的HTML控件上,例如text,图片   包含:1.界面滤镜  (Procedural Surfaces)2.静态滤 ...

  4. tamper-proof 对象 nonextensible对象 sealed对象 frozen对象

    tamper-proof 对象JavaScript的缺点之一就是每个对象都可以被相同执行上下文的代码修改,很容易导致意外覆盖,或则一不小心把native 对象覆盖.Ecmascript  5提供了 t ...

  5. vue初级学习--环境搭建

    一.导语 最近总想学点东西,es6啊.typescript啊,都想学,刚好有个机遇,可以学点vue,嗯,那就开始吧. 二.正文 1.node环境: 下载安装nodeJs,最好是1.6以上的版本,下载地 ...

  6. 使用SQLPLUS创建用户名和表空间

    用sqlplus为oracle创建用户和表空间用sqlplus为oracle创建用户和表空间用Oracle10g自带的企业管理器或PL/SQL图形化的方法创建表空间和用户以及分配权限是相对比较简单的, ...

  7. java Mybatis框架动态SQL

    1.if+where <select id="getgoods" resultType="Goods" > select * from goods ...

  8. 让ffmpeg支持10bit编码

    文章版权由作者柯O德尔和博客园共有,请尊重并支持原创,若转载请于明显处标明出处:http://www.cnblogs.com/koder/ 最近因为工作需要,要进行265 10bit编码,于是从ffm ...

  9. ES6中class关键字

    1 .介绍 //定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + th ...

  10. Python的egg包

    1.背景 查看flower的源码,首先看到flower的主程序如下: #!/usr/local/sinasrv2/bin/python2.7 # EASY-INSTALL-ENTRY-SCRIPT: ...