【Hibernate框架】关联映射(一对多,多对一)
根据我们的总结计划,上篇文章我们总结了有关于一对一映射相关知识,接下来,我们进行下一个阶段,一对多、多对一映射相关知识。
场景设定:
国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工。我们就利用这个场景,根据针对对象的不同,我们分别来分析一下一对多、多对一关联映射。
一、多对一单向关联映射
1、多对一单向关联映射:对于员工(Employee)来说,他跟公司(Company)的对应关系就是多对一关系
Po对象:Employee.Java
- public class Employee {
- public int id;
- public String name;
- public Company company;
- //getter、setter
- }
Company.java
- public class Company{
- public int id;
- public String name;
- //getter、setter
- }
作为程序员,我们都知道在设计数据库要在多对一的多那一面添加一的外键,所以我们在员工类中,添加对公司类的引用。
映射文件:Employee.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Employee" table="t_employee">
- <id name="id" type="int">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <many-to-one name="company" column="companyid"/>
- </class>
- </hibernate-mapping>
Company.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Company" table="t_company">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- </class>
- </hibernate-mapping>
执行程序自动生成表:
- create table t_company (id integer not null auto_increment, name varchar(255), primary key (id))
- create table t_employee (id integer not null auto_increment, name varchar(255), companyid integer, primary key (id))
测试:
- session.beginTransaction();
- Company company=new Company();
- company.setName("某某集团");
- session.save(company);//这里必须要先save一下company,将之变成持久化状态否则会因为无法保存瞬时对象而报错
- Employee employee1=new Employee();
- employee1.setName("路人甲");
- employee1.setCompany(company);
- Employee employee2=new Employee();
- employee2.setName("路人乙");
- employee2.setCompany(company);
- session.save(employee1);
- session.save(employee2);
- session.getTransaction().commit();
执行结果:
- Hibernate: insert into Company (id,name) values (?,?)
- Hibernate: insert into Employee (id,name,companyid) values (?,?,?)
值得一提的是,如果我们没有在测试程序里面session.save(company),直接执行程序,我们会报错,但是解决办法绝不是只有这一种,我们还可以在员工Employee映射文件中的<many-to-one/>中配置cascade属性:
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssm.hibernate.Employee" table="t_employee">
- <id name="id" type="int">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <many-to-one name="company" column="companyid" cascade="save-update"/>
- <!--在这里配置cascade属性,表示两个对象之间的操作为联动关系-->
- </class>
- </hibernate-mapping>
关于cascade的一些属性值分别是:persist, merge, delete, save-update, evict, replicate, lock, refresh
二、一对多单向关联映射:
同样适用上面的场景设定:国家规定一个员工只能在一个公司上班,但是一个公司可以拥有很多员工。这时候,针对公司来说,就是一对多关系了。像这种时候,我们就需要在公司类中添加一个对员工对象的集合了。这个集合可以是set、list、map、array数组的有关容器(其中set中的对象不可重复,相对性能也比较高,建议使用set)
Po对象:Employee.java
- public class Employee{
- public int id;
- public String name;
- //getter、setter
- }
Company.java
- public class Company{
- public int id;
- public String name;
- public Set<Employee> employees;
- //getter、setter
- }
映射文件:Employee.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Employee" table="t_employee">
- <id name="id" type="int">
- <generator class="native"/>
- </id>
- <property name="name"/>
- </class>
- </hibernate-mapping>
Company.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Company" table="t_company">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name=employees>
- <key column="companyid"></key><!-- "多"的一方关联"一"的一方的外键 -->
- <one-to-many class="com.ssh.hibernate.Employee"/><!-- 一个Company对象对应多个Employee对象 -->
- </set>
- </class>
- </hibernate-mapping>
测试:
- session.beginTransaction();
- Employee employee1=new Employee();
- employee1.setName("路人甲");
- session.save(employee1)
- Employee employee2=new Employee();
- employee2.setName("路人乙");
- employee2.save(employee2);
- Set<Employee> employees=new HashSet<Employee>();
- employees.add(employee1);
- employees.add(employee2);
- Company company=new Company();
- company.setName("某某集团");
- company.setEmployees(employees);
- session.save(company);
- session.getTransaction().commit();
事务提交数据插入之后,我们进行查询:
- session.beginTransaction();
- Company company=(Company)session.load(Company.class,1);
- System.out.println("公司名称:"+company.getName());
- System.out.println("公司员工:");
- for(Employee employee:company.getEmployees()){
- System.out.print(" "+employee.getName());
- }
- session.getTransaction().commit();
查询结果:
- Hibernate: select company0_.id as id0_0_, company0_.name as name0_0_ from t_company company0_
- where company0_.id=?
- 公司名称:某某集团
- 公司员工:Hibernate: select employees0_.companyid as company3_1_, employees0_.id as id1_,
- employees0_.id as id1_0_,employees0_.name as name1_0_ from t_employee employees0_
- where employees0_.companytid=?
- 路人甲 路人乙
从控制台消息来看,还能延迟加载lazy,那如果我们把配置文件改为:
Company.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Company" table="t_company">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name=employees lazy="false"><!--如果这里将lazy设置成false,将禁止延迟加载,默认为true-->
- <key column="companyid"></key><!-- "多"的一方关联"一"的一方的外键 -->
- <one-to-many class="com.ssh.hibernate.Employee"/><!-- 一个Company对象对应多个Employee对象 -->
- </set>
- </class>
- </hibernate-mapping>
三、多对一/一对多双向关联映射
现在我们还是用上面的场景设定来实现一对多/多对一双向关联:
Po对象:Company.java
- public class Company{
- public int id;
- public String name;
- public Set<Employee> employees;
- //getter、setter
- }
Employee.java
- public class Employee {
- public int id;
- public String name;
- public Company company;
- //getter、setter
- }
配置文件:Employee.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Employee" table="t_employee">
- <id name="id" type="int">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <many-to-one name="company" column="companyid" not-null="true">
- </class>
- </hibernate-mapping>
Company.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Company" table="t_company">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name="employees">
- <key column="companyid"></key>
- <one-to-many class="com.ssh.hibernate.Employee"/>
- </set>
- </class>
- </hibernate-mapping>
如果你使用List(或者其他有序集合类),你需要设置外键对应的key列为 not null,让Hibernate来从集合端管理关联,维护每个元素的索引(通过设置update="false" and insert="false"来对另一端反向操作):
Employee.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Employee" table="t_employee">
- <id name="id" type="int">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <many-to-one name="company" column="companyid" not-null="true" insert="flase" update="false"/>
- </class>
- </hibernate-mapping>
Company.hbm.xml
- <hibernate-mapping package="org.hibernate.test" >
- <class name="com.ssh.hibernate.Company" table="t_company">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <list name="employees">
- <key column="companyid" not-null="true"></key>
- <list-index column="employeeId"/>
- <one-to-many class="com.ssh.hibernate.Employee"/>
- </set>
- </class>
- </hibernate-mapping>
假若集合映射的<key>元素对应的底层外键字段是NOT NULL的,那么为这一key元素定义not-null="true"是很重要的。不要仅仅为可能的嵌套<column>元素定义not-null="true",<key>元素也是需要的。
四、总结:
1、对于单向的一对多、多对一关联映射,建表时,都是在“多”的一端添加外键指向“一”的一端。而他们的不同点就是维护关系的不同,也可理解为主表变更,由谁指向谁的关系变了。
2、对于双向的一对多/多对一来说,他们之间本就是互为指向的,只是要注意我们需用的方法的不同来针对不同的地方进行配置。使用set、list的时候,大体上是差不多的,关键就是使用list的时候,多对一从表的逐渐不可自己更添,而一对多从表主/外键id不能为空
【Hibernate框架】关联映射(一对多,多对一)的更多相关文章
- Hibernate之关联映射(一对多和多对一映射,多对多映射)
~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...
- Hibernate框架--关联映射,一对多,多对多 inverse cascade
回顾Hibernate: 1. hibernate开发环境搭建 ----> 引入jar: hibernate.jar + required + jpa + 驱动包 ---> hiberna ...
- Hibernate框架关系映射一对多双向关联
直入主题,首先大配置常规配置, 这里住要说关联关系,大配置不多少,而且jar包默认添加好,笔者用的是idea2016. 然后我们知道关联关系主要是在小配置添加节点来配置属性.个人认为关联映射,就是对应 ...
- Hibernate的关联映射--一对多、
这是我 1 单向一对多: 实体类:(课程类)Grade与(学生类)Student的一对多关系 学生类: public class Student implements java.io.Serializ ...
- Hibernate框架学习(六)——一对多&多对一关系
一.关系表达 1.表中的表达 2.实体中的表达 3.orm元数据中的表达 一对多:(在Customer.hbm.xml中添加) 多对一:(在LinkMan.hbm.xml中添加) 最后别忘了在hibe ...
- (转)Hibernate关联映射——一对多(多对一)
http://blog.csdn.net/yerenyuan_pku/article/details/70152173 Hibernate关联映射——一对多(多对一) 我们以客户(Customer)与 ...
- Hibernate之关联关系映射(一对多和多对一映射,多对多映射)
~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习一下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...
- Hibernatel框架关联映射
Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...
- Hibernate注解----关联映射注解以及课程总结详解----图片版本
上一篇,记录了Hibernate注解----类级别注解以及属性注解详解 ,我们这一节主要讲解的是Hibernate注解----关联映射注解以及课程总结详解. 本节的主要内容: 第3章 关联映射注解 3 ...
- 初识Hibernate之关联映射(二)
上篇我们介绍了关联映射的几种形式,有单向多对一,单向一对多,还有双向一对多.本篇接着介绍有关关联映射的其他几种映射方式,主要有以下几种: 基于外键的单向一对一关联映射 基于主键的单向一对一关联映射 单 ...
随机推荐
- .gitignore过滤个人配置
git还是一个很好使用的版本工具.所以用eclipse做自己的小玩意儿,在多台电脑之间同步的时候我经常会使用它.. 但是有个问题..不同电脑的eclipse的个人配置稍微有那么一点点的不同..比如有几 ...
- Git Stash紧急处理问题,需要切分支
在开发过程中,大家都遇到过bug,并且有些bug是需要紧急修复的. 当开发人员遇到这样的问题时,首先想到的是我新切一个分支,把它修复了,再合并到master上. 当时问题来了,你当前正在开发的分支上面 ...
- DHCP
安装 yum install -y dhcp 配置文件 默认配置为/etc/dhcpd.conf [root@samba ~]# [root@samba ~]# rpm -ql dhcp | grep ...
- centos7 cannot find a valid baseurl for repo base (转载)
centos7 cannot find a valid baseurl for repo base 今天在虚拟机下安装centosmini版本,安装后第一件事就是yum update 但是有错 ...
- http://875880923.iteye.com/blog/1963400
已经接触了一段时间的ACM(详见百度百科)了,每回刷杭电oj的题累了的时候,就喜欢去看Ranklist里面的排名,看看前面的牛人的格言,让自己有一点憧憬.有一天突然好奇杭电上的人做的总题数的数量与人数 ...
- 【原创】CSS高效开发实战:CSS 3、LESS、SASS、Bootstrap、Foundation --读书笔记(5)使用放射渐变制作光影效果
阴影效果通常用来表现光线投射在物体上的感觉,如果想制作一个如图5.19所示的文字光影效果,就可以使用背景的线性渐变进行构建. 图5.19可以看到有类似光束照射文字的效果,很好地突出了文字.这实现起来很 ...
- PHP中常见的提示对照表
.Notice: Undefined variable: 变量名 in 注:使用了一个没有被定义的变量 .Parse error: syntax error, unexpected T_ELSE in ...
- Web干货存档
今天看了某乎,介绍了web一些基本东西,讲的很好,随手留下https://www.zhihu.com/question/22689579 web开发者文档,纯干货 https://develope ...
- PPM图片格式及其C读写代码
PPM图像格式介绍 PPM图像格式是由Jef Poskanzer 大叔,在我出生那一年,也就是1991年所创造的,碰巧的是PPM也是天蝎座. PPM(Portable Pixmap Format)还有 ...
- Unity3D 原生Android结合UnityPlayerActivity开发遇到的问题
需求是原生Android 的Activity启动UnityPlayerActivity,按Back键后返回原来的Activity 1.在AndroidManifest.xml中的UnityPlayer ...