根据我们的总结计划,上篇文章我们总结了有关于一对一映射相关知识,接下来,我们进行下一个阶段,一对多、多对一映射相关知识。

场景设定:

国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工。我们就利用这个场景,根据针对对象的不同,我们分别来分析一下一对多、多对一关联映射。

一、多对一单向关联映射

1、多对一单向关联映射:对于员工(Employee)来说,他跟公司(Company)的对应关系就是多对一关系

Po对象:Employee.Java

  1. public class Employee {
  2. public int id;
  3. public String name;
  4. public Company company;
  5. //getter、setter
  6. }

Company.java

  1. public class Company{
  2. public int id;
  3. public String name;
  4. //getter、setter
  5. }

作为程序员,我们都知道在设计数据库要在多对一的多那一面添加一的外键,所以我们在员工类中,添加对公司类的引用。

映射文件:Employee.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Employee" table="t_employee">
  3. <id name="id" type="int">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <many-to-one name="company" column="companyid"/>
  8. </class>
  9. </hibernate-mapping>  

Company.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Company" table="t_company">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. </class>
  8. </hibernate-mapping>

执行程序自动生成表:

  1. create table t_company (id integer not null auto_increment, name varchar(255), primary key (id))
  2. create table t_employee (id integer not null auto_increment, name varchar(255), companyid integer, primary key (id))

测试

  1. session.beginTransaction();
  2. Company company=new Company();
  3. company.setName("某某集团");
  4. session.save(company);//这里必须要先save一下company,将之变成持久化状态否则会因为无法保存瞬时对象而报错
  5. Employee employee1=new Employee();
  6. employee1.setName("路人甲");
  7. employee1.setCompany(company);
  8. Employee employee2=new Employee();
  9. employee2.setName("路人乙");
  10. employee2.setCompany(company);
  11. session.save(employee1);
  12. session.save(employee2);
  13. session.getTransaction().commit();

执行结果:

  1. Hibernate: insert into Company (id,name) values (?,?)
  2. Hibernate: insert into Employee (id,name,companyid) values (?,?,?)

值得一提的是,如果我们没有在测试程序里面session.save(company),直接执行程序,我们会报错,但是解决办法绝不是只有这一种,我们还可以在员工Employee映射文件中的<many-to-one/>中配置cascade属性:

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssm.hibernate.Employee" table="t_employee">
  3. <id name="id" type="int">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <many-to-one name="company" column="companyid" cascade="save-update"/>
  8. <!--在这里配置cascade属性,表示两个对象之间的操作为联动关系-->
  9. </class>
  10. </hibernate-mapping>

关于cascade的一些属性值分别是:persist, merge, delete, save-update, evict, replicate, lock, refresh

二、一对多单向关联映射:

同样适用上面的场景设定:国家规定一个员工只能在一个公司上班,但是一个公司可以拥有很多员工。这时候,针对公司来说,就是一对多关系了。像这种时候,我们就需要在公司类中添加一个对员工对象的集合了。这个集合可以是set、list、map、array数组的有关容器(其中set中的对象不可重复,相对性能也比较高,建议使用set)

Po对象:Employee.java

  1. public class Employee{
  2. public int id;
  3. public String name;
  4. //getter、setter
  5. }

Company.java

  1. public class Company{
  2. public int id;
  3. public String name;
  4. public Set<Employee> employees;
  5. //getter、setter
  6. }

映射文件:Employee.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Employee" table="t_employee">
  3. <id name="id" type="int">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. </class>
  8. </hibernate-mapping>

Company.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Company" table="t_company">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <set name=employees>
  8. <key column="companyid"></key><!-- "多"的一方关联"一"的一方的外键 -->
  9. <one-to-many class="com.ssh.hibernate.Employee"/><!-- 一个Company对象对应多个Employee对象 -->
  10. </set>
  11. </class>
  12. </hibernate-mapping>

测试:

  1. session.beginTransaction();
  2. Employee employee1=new Employee();
  3. employee1.setName("路人甲");
  4. session.save(employee1)
  5. Employee employee2=new Employee();
  6. employee2.setName("路人乙");
  7. employee2.save(employee2);
  8. Set<Employee> employees=new HashSet<Employee>();
  9. employees.add(employee1);
  10. employees.add(employee2);
  11. Company company=new Company();
  12. company.setName("某某集团");
  13. company.setEmployees(employees);
  14. session.save(company);
  15. session.getTransaction().commit();

事务提交数据插入之后,我们进行查询:

  1. session.beginTransaction();
  2. Company company=(Company)session.load(Company.class,1);
  3. System.out.println("公司名称:"+company.getName());
  4. System.out.println("公司员工:");
  5. for(Employee employee:company.getEmployees()){
  6. System.out.print(" "+employee.getName());
  7. }
  8. session.getTransaction().commit();

查询结果:

  1. Hibernate: select company0_.id as id0_0_, company0_.name as name0_0_ from t_company company0_
  2. where company0_.id=?
  3. 公司名称:某某集团
  4. 公司员工:Hibernate: select employees0_.companyid as company3_1_, employees0_.id as id1_,
  5. employees0_.id as id1_0_,employees0_.name as name1_0_ from t_employee employees0_
  6. where employees0_.companytid=?
  7. 路人甲 路人乙

从控制台消息来看,还能延迟加载lazy,那如果我们把配置文件改为:

Company.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Company" table="t_company">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <set name=employees lazy="false"><!--如果这里将lazy设置成false,将禁止延迟加载,默认为true-->
  8. <key column="companyid"></key><!-- "多"的一方关联"一"的一方的外键 -->
  9. <one-to-many class="com.ssh.hibernate.Employee"/><!-- 一个Company对象对应多个Employee对象 -->
  10. </set>
  11. </class>
  12. </hibernate-mapping>

三、多对一/一对多双向关联映射

现在我们还是用上面的场景设定来实现一对多/多对一双向关联:

Po对象:Company.java

  1. public class Company{
  2. public int id;
  3. public String name;
  4. public Set<Employee> employees;
  5. //getter、setter
  6. }

Employee.java

  1. public class Employee {
  2. public int id;
  3. public String name;
  4. public Company company;
  5. //getter、setter
  6. }

配置文件:Employee.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Employee" table="t_employee">
  3. <id name="id" type="int">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <many-to-one name="company" column="companyid" not-null="true">
  8. </class>
  9. </hibernate-mapping>

Company.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Company" table="t_company">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <set name="employees">
  8. <key column="companyid"></key>
  9. <one-to-many class="com.ssh.hibernate.Employee"/>
  10. </set>
  11. </class>
  12. </hibernate-mapping>

如果你使用List(或者其他有序集合类),你需要设置外键对应的key列为 not null,让Hibernate来从集合端管理关联,维护每个元素的索引(通过设置update="false" and insert="false"来对另一端反向操作):

Employee.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Employee" table="t_employee">
  3. <id name="id" type="int">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <many-to-one name="company" column="companyid" not-null="true" insert="flase" update="false"/>
  8. </class>
  9. </hibernate-mapping>

Company.hbm.xml

  1. <hibernate-mapping package="org.hibernate.test" >
  2. <class name="com.ssh.hibernate.Company" table="t_company">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <list name="employees">
  8. <key column="companyid" not-null="true"></key>
  9. <list-index column="employeeId"/>
  10. <one-to-many class="com.ssh.hibernate.Employee"/>
  11. </set>
  12. </class>
  13. </hibernate-mapping>

假若集合映射的<key>元素对应的底层外键字段是NOT NULL的,那么为这一key元素定义not-null="true"是很重要的。不要仅仅为可能的嵌套<column>元素定义not-null="true",<key>元素也是需要的。

四、总结:

1、对于单向的一对多、多对一关联映射,建表时,都是在“多”的一端添加外键指向“一”的一端。而他们的不同点就是维护关系的不同,也可理解为主表变更,由谁指向谁的关系变了。

2、对于双向的一对多/多对一来说,他们之间本就是互为指向的,只是要注意我们需用的方法的不同来针对不同的地方进行配置。使用set、list的时候,大体上是差不多的,关键就是使用list的时候,多对一从表的逐渐不可自己更添,而一对多从表主/外键id不能为空

【Hibernate框架】关联映射(一对多,多对一)的更多相关文章

  1. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  2. Hibernate框架--关联映射,一对多,多对多 inverse cascade

    回顾Hibernate: 1. hibernate开发环境搭建 ----> 引入jar: hibernate.jar + required + jpa + 驱动包 ---> hiberna ...

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

    直入主题,首先大配置常规配置, 这里住要说关联关系,大配置不多少,而且jar包默认添加好,笔者用的是idea2016. 然后我们知道关联关系主要是在小配置添加节点来配置属性.个人认为关联映射,就是对应 ...

  4. Hibernate的关联映射--一对多、

    这是我 1 单向一对多: 实体类:(课程类)Grade与(学生类)Student的一对多关系 学生类: public class Student implements java.io.Serializ ...

  5. Hibernate框架学习(六)——一对多&多对一关系

    一.关系表达 1.表中的表达 2.实体中的表达 3.orm元数据中的表达 一对多:(在Customer.hbm.xml中添加) 多对一:(在LinkMan.hbm.xml中添加) 最后别忘了在hibe ...

  6. (转)Hibernate关联映射——一对多(多对一)

    http://blog.csdn.net/yerenyuan_pku/article/details/70152173 Hibernate关联映射——一对多(多对一) 我们以客户(Customer)与 ...

  7. Hibernate之关联关系映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习一下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  8. Hibernatel框架关联映射

    Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...

  9. Hibernate注解----关联映射注解以及课程总结详解----图片版本

    上一篇,记录了Hibernate注解----类级别注解以及属性注解详解 ,我们这一节主要讲解的是Hibernate注解----关联映射注解以及课程总结详解. 本节的主要内容: 第3章 关联映射注解 3 ...

  10. 初识Hibernate之关联映射(二)

    上篇我们介绍了关联映射的几种形式,有单向多对一,单向一对多,还有双向一对多.本篇接着介绍有关关联映射的其他几种映射方式,主要有以下几种: 基于外键的单向一对一关联映射 基于主键的单向一对一关联映射 单 ...

随机推荐

  1. MyEclipse安装插件的几种方法

    本文讲解MyEclipse(MyEclipse10)的三种方法,以SVN为例 Eclipse update site URL: http://subclipse.tigris.org/update_1 ...

  2. hdu2005第几天?

    Problem Description 给定一个日期,输出这个日期是该年的第几天.   Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input , ...

  3. 实战动态PDF在线预览及带签名的PDF文件转换

    开篇语: 最近工作需要做一个借款合同,公司以前的合同都是通过app端下载,然后通过本地打开pdf文件,而喜欢创新的我,心想着为什么不能在线H5预览,正是这个想法,说干就干,实践过程总是艰难的,折腾了3 ...

  4. KMP专题

    1.[HDU 3336]Count the string(KMP+dp) 题意:求给定字符串含前缀的数量,如输入字符串abab,前缀是a.ab.aba.abab,在原字符串中出现的次数分别是2.2.1 ...

  5. HTML 内容居中方式总结

    在HTML网页排版经常会用到关于对其方式的情况,水平居中和垂直居中.特别是水平居中,并不是一个简单的text-align就可以解决所有的情况. 开始之前普及一点HTML知识,目标很明显,不同的页面结构 ...

  6. js之认识闭包

    本文采用5W1H分析法来看一下闭包. 一.why-----从为什么要引入闭包先来了解一下闭包. 讨论为什么要引入闭包就要先讨论一下js中的作用域链及垃圾回收机制. 熟悉js语言的人都知道js中有作用域 ...

  7. Life Is A Funny Proposition After All

    你们有没有坐下思考,感到疑惑 ,静静思考,我们为什么在这里 ,生活为什么如此这般 这个问题让无数聪明人喝酒买醉,这是最最奇怪的事情,他们都想弄清楚,科学家们可以展示上千种不同的理论,但从未证明这是为什 ...

  8. maven实战(01)_搭建开发环境

    一 下载maven 在maven官网上可下载maven:http://maven.apache.org/download.cgi 下载好后,解压.我的解压到了:D:\maven\apache-mave ...

  9. php mysqli mysqli_query() mysqli_real_query()

    2016年11月26日 15:22:27 星期六 场景: PHP从mysql中读取数据 1. 一次性读取所有数据返给PHP 2. 每次循环只读取一掉记录 数据量小的时候可以使用第一种方法, 数据量很大 ...

  10. Cnblogs自定义皮肤css样式-星空观测者

    不知不觉来Cnblogs也这么久了,然而Blogs提供的主题还是依旧那么复古,总觉得阅读起来难免枯燥,虽然我认为做技术不可以太过浮躁,但是一个美观的主题终究是吸引人眼的第一要素. 毕竟这么久了,在博客 ...