导读

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

一、一对多关系

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

1、数据库的实现

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

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、测试

  1. package Test;
  2.  
  3. import org.hibernate.Session;
  4. import org.hibernate.Transaction;
  5. import org.junit.Test;
  6.  
  7. import domain.Course;
  8. import domain.Student;
  9. import utils.HibernateUtils;
  10.  
  11. public class Demo2 {
  12. @Test
  13. public void test(){
  14. //1、创建对话session
  15. Session session = HibernateUtils.openSession();
  16. //2、开启事务
  17. Transaction tx = session.beginTransaction();
  18.  
  19. //3、操作事务:假设有语数外三门课,张三选了语文和数学,李四选了语文和英语,Tom选了数学。将上述信息持久化到数据库
  20. //---------------------------------
  21. //创建实体对象
  22. Course c1 = new Course();
  23. c1.setCname("语文");
  24. Course c2 = new Course();
  25. c2.setCname("数学");
  26. Course c3 = new Course();
  27. c3.setCname("英语");
  28.  
  29. Student s1 = new Student();
  30. s1.setSname("张三");
  31. Student s2 = new Student();
  32. s2.setSname("李四");
  33. Student s3 = new Student();
  34. s3.setSname("Tom");
  35.  
  36. //建立对象之间的关系
  37. //课程对应学生
  38. c1.getStudentSet().add(s1);
  39. c1.getStudentSet().add(s2);
  40. c2.getStudentSet().add(s2);
  41. c2.getStudentSet().add(s3);
  42. c3.getStudentSet().add(s2);
  43.  
  44. //学生对应课程
  45. s1.getCourseSet().add(c1);
  46. s1.getCourseSet().add(c2);
  47. s2.getCourseSet().add(c2);
  48. s2.getCourseSet().add(c3);
  49. s3.getCourseSet().add(c2);
  50.  
  51. //将信息持久化到数据库
  52. session.save(c1);
  53. session.save(c2);
  54. session.save(c3);
  55. session.save(s1);
  56. session.save(s2);
  57. session.save(s3);
  58. //----------------------------------
  59.  
  60. //4、提交事务
  61. tx.commit();
  62. //5、关闭资源
  63. session.close();
  64. }
  65. }

测试结果:

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. 业余草双因素认证(2FA)教程

    所谓认证(authentication)就是确认用户的身份,是网站登录必不可少的步骤.密码是最常见的认证方法,但是不安全,容易泄露和冒充.越来越多的地方,要求启用双因素认证(Two-factor au ...

  2. 微信公众号开发(十二)OAuth2.0网页授权

    OAuth允许用户提供一个令牌,而不是用户名和密码来访问它们存放在特定服务器上的数据,每一个令牌授权一个特定的网站在特定时段内访问特定的资源. 授权过程如下: 1.引导用户进入授权页面同意授权,获取c ...

  3. 《Spark Python API 官方文档中文版》 之 pyspark.sql (二)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  4. 「设计模式」JavaScript - 设计模式之单例模式与场景实践

    单例介绍 上次总结了设计模式中的module模式,可能没有真真正正的使用在场景中,发现效果并不好,想要使用起来却不那么得心应手, 所以这次我打算换一种方式~~从简单的场景中来看单例模式, 因为Java ...

  5. JavaNIO非阻塞模式

    package com.java.NIO; import java.io.IOException; import java.net.InetSocketAddress; import java.nio ...

  6. AngularJS学习篇(十七)

    AngularJS 输入验证 <!DOCTYPE html> <html> <script src="http://apps.bdimg.com/libs/an ...

  7. Grunt参考

    Grunt参考: http://www.cnblogs.com/yexiaochai/p/3603389.html http://blog.csdn.net/wangfupeng1988/articl ...

  8. 开发环境MAPLAB下使用仿真器ICD2程序下载流程

    程序下载流程 一.    连接示意图 二.    下载步骤 1.目标板电源断开 2.将仿真器下载端口与电路板JTAG端口有效连接 3.启动MPLAB软件 4.点击MAPLAB软件上方Programme ...

  9. Celery 源码解析四: 定时任务的实现

    在系列中的第二篇我们已经看过了 Celery 中的执行引擎是如何执行任务的,并且在第三篇中也介绍了任务的对象,但是,目前我们看到的都是被动的任务执行,也就是说目前执行的任务都是第三方调用发送过来的.可 ...

  10. Velocity(6)——velocity遍历josn格式的字符串

    使用velocity脚本语言遍历josn格式的字符串 1.由于数据库会存储一些json格式的字符,为方便以后使用筛选 如果这些数据我们查出来直接遍历使用velocity是根本行不通的,例如这样的话:j ...