我们所生活的世界很少有事物是孤立存在的,每个事物必然会存在着与它相关联的事物。在面向对象设计当中,关联关系是非常重要的。关联关系一般可以分为以下两种:

单向关系:只需单向访问关联端

双向关系:关联的两端都可以互相访问

单向关系可分为:1—N、1—1、N—1、N—N

双向关系可分为:1—1 、1—N、N—N

下面就上面的每种关联映射分别讲解:

一、N—1关联映射

1、单向N—1关联

1.1、无连接表的N-1关联(基于外键的N-1关联)

对于单向的N—1关联而言只需要从N的一端可以访问1的一端。为了让这个两个持久化类支持这种关联映射,程序应该在N的一端的持久化类中增加一个熟悉,该属性引用1一端的关联实体。

两个关联属性如下(以员工和部门之间的关系为例):

Employee:

public class Employee {private Integer id;private String name;private Department department;    //关联属性public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Department getDepartment() {return department;}public void setDepartment(Department department) {this.department = department;}}

Department:

public class Department {private Integer id;private String name;private Set<Employee> employees;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Set<Employee> getEmployees() {return employees;}public void setEmployees(Set<Employee> employees) {this.employees = employees;}}

Employee端增加了Department属性,该属性并不是一个普通的组件属性,而是引用另一个持久化类的类。Hibernate使用<many-to-one.../>元素映射N—1的关联实体,直接采用<many-to-one.../>元素来映射关联实体将会在N的一端的数据表中增加一个外键,用于参照主表记录。

下面为两个实体的映射文件:

Employee.hbm.xml

在这个映射文件中需要用<many-to-one../>来完成关联映射

<hibernate-mapping package="com.hibernate.domain"><class name="Employee" table="employee"><id name="id" column="employeeID"><generator class="native" /></id><property name="name" column="employeeName" /><!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID--><many-to-one class="Department" name="department" column="departmentID" not-null="true"    cascade="all"/> </class>
</hibernate-mapping>

Department.hbm.xml

<hibernate-mapping package="com.hibernate.domain" ><class name="Department" table="department"><id name="id" column="departmentID"><generator class="native" /></id><property name="name" column="departmentName" /></class>
</hibernate-mapping>

通过上面的映射后,就可以使用如下代码来保存Employee和Department实体了。

   //增加static void add() {Session s = null;Transaction tx = null;try {s = HibernateUtil.getSession();tx = s.beginTransaction();Department depart = new Department();           //....1depart.setName("组织部");Employee emp = new Employee();//对象模型:建立两个对象的关联关系emp.setDepartment(depart);                     //...2 emp.setName("汤妹彤");s.save(depart);                               //...3s.save(emp);                                  //...4tx.commit();} finally {if (s != null)s.close();}}

代码分析:

当代码运行到...1的时候会创建一个瞬态的Department对象。当程序运行到...3和...4的时候,系统就会分别保存Department对象和Employee对象。会产生如下两条SQL语句:

        Hibernate: insert into department (departmentName) values (?)Hibernate: insert into employee (employeeName, departmentID) values (?, ?)

...2这条语句非常重要,因为它是建立Department和Employee两个对象的关联关系。没有这条语句是无法建立两个对象的关系。

在这里我们将...3语句和...4两条语句交换位置。这时运行就会产生三条SQL语句。当...3的时候,departmentID插入的时候为空,只有当持久化Department对象后,系统就会将departmentID修改为相对应的值。如下:

Hibernate: insert into employee (employeeName, departmentID) values (?, ?)Hibernate: insert into department (departmentName) values (?)Hibernate: update employee set employeeName=?, departmentID=? where employeeID=?

如果我们在Employee.hbm.xml映射文件中,给外键添加一个非空约束,即:

<many-to-one class="Department" name="department" column="departmentID" not-null="true"/>

上面的代码就会报空异常:org.hibernate.PropertyValueException: not-null property references a null or transient value。

如果我们不想改变上面代码,又要能够执行。即先持久化从表。对于这种情况我们可以设置级联:cascade="all".即

<many-to-one class="Department" name="department" column="departmentID" not-null="true" cascade="all"/>。

通过指定了cascade="all"。这就意味着系统将先自动级联插入主表记录。

所以在所有基于外键约束的关联关系中,我们必须牢记:要么总是先持久化主表对应的实体,要么设置级联操作。否则当Hibernate试图插入从表记录时,如果发现该从表参照的主表记录不存在,一定会抛出异常。

2、有连接表的N-1关联

对于绝大部分的单向N-1关联而言,使用基于外键的关联映射就可以了。但是如果需要使用连接表来映射单向N-1关联,则需要使用<join.../>元素,该元素用于强制将一个类的属性映射到多张表中。

使用<join.../>元素映射到连接表时,需要外键关联,应在配置文件中增加<key.../>子元素来映射外键,并为<join.../>元素增加<many-to-one.../>子元素来映射N-1的关联实体。如下:

<hibernate-mapping package="com.hibernate.domain"><class name="Employee" table="employee"><id name="id" column="employeeID"><generator class="native" /></id><property name="name" column="employeeName" /><!-- 使用join元素强制使用连接表 --><join table="employee_department"><!-- 映射连接表中参照本表主键的外键列 --><key column="employeeID" /><!-- 映射连接表参照关联实体的外键列 --><many-to-one name="department" class="Department" column="departmentID" /></join>    </class>
</hibernate-mapping>

读李刚《轻量级Java EE 企业应用实战》

转载于:https://www.cnblogs.com/oversea201405/archive/2012/07/03/3752342.html

Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射相关推荐

  1. Hibernate读书笔记---继承映射

    对于面向对象的程序设计语言,继承.多态是两个最基本的概念.Hibernate的继承映射可以理解两个持久化类之间的继承关系. Hibernate支持几种继承映射策略,不管哪种继承映射策略,Hiberna ...

  2. Hibernate读书笔记

    伟大的信息管理与信息系统专业,万恶的信息管理与信息系统专业.说这句话我是有根据的:因为这个专业雄心勃勃的想把自己的子弟培养成全面发展的人才但是结果则不然.两方面的原因:一部分在学生,但是一部分在这个专 ...

  3. Hibernate课堂笔记

    Hibernate课堂笔记 Hibernate第一天 一:hibernate的基础知识 Hibernate的整体思想就是"操作对象的过程,就是操作数据库表的过程".如图: 1:Hi ...

  4. 机器学习实战---读书笔记: 第11章 使用Apriori算法进行关联分析---2---从频繁项集中挖掘关联规则

    #!/usr/bin/env python # encoding: utf-8''' <<机器学习实战>> 读书笔记 第11章 使用Apriori算法进行关联分析---从频繁项 ...

  5. 《妙解Hibernate 3.X》读书笔记一-Hibernate概述及环境搭建

    很早就想开始Hibernate的系统学习,但是一是工作原因,二是苦于找不到合适的书籍.Hibernate更新较快,一些被称为经典的书籍,如<深入浅出Hibernate>.<Hiber ...

  6. Hibernate 关联映射 之 多对多 关联(二) 之拆分

    1.由问题引出一个多对多拆分成两个多对一 问题:Hibernate 关联映射 之 多对多 关联(一)中中间表只是一个存放用户和角色的表,并无其他作用,如果客户有其他的需求,该表就无法扩展. 2.问题解 ...

  7. Hibernate学习笔记--映射配置文件详解

    参考资料: http://blog.163.com/hzd_love/blog/static/13199988120108265317988/ http://www.cnblogs.com/often ...

  8. Hibernate学习笔记--第二篇 关联关系映射 many –to –one

    many –to –one 假设2个对象,分别是Person and Address . 1个Address中含有多个Person 分别建立类 package cn.itcase.hibernate. ...

  9. hibernate学习笔记(总结)

    hibernate学习笔记 课程内容 6 1 HelloWorld 6 2 Hibernate原理模拟-什么是O/R Mapping以及为什么要有O/R Mapping 6 3 常见的0/R框架(了解 ...

  10. 马士兵Hibernate学习笔记

    马士兵hibernate学习笔记 课程内容 6课程内容 1 HelloWorld 6 2 Hibernate原理模拟-什么是O/R Mapping以及为什么要有O/R Mapping 6 3 常见的0 ...

最新文章

  1. 开源软件License汇总
  2. 参加软件测试培训前景怎么样
  3. 赠书:啥是指标陷阱?很多就出现在你的身边!
  4. Spring Boot——AbstractWebSocketMessageBrokerConfigurer已过时解决方案
  5. Nhibernate 基础关系映射
  6. VTK:libvtkGUISupportQt-6.3.so.1: cannot open shared object
  7. NYOJ 289 苹果(01背包)
  8. 接口访问超时 504 Gateway Time-out 优化方案
  9. insert同时添加两张表_Q语言——表的高级查询语言(一)
  10. Vue + OpenLayers 配置多个地图数据源
  11. php引用字体,php – 使用imagettftext()时,如何处理字体文件不支持的字符?
  12. Java实习日记(4)
  13. 流体力学专业常用网站集合
  14. 基于51单片机的温度检测调节系统设计
  15. 把整个网页下载下来的方法
  16. 绝了!多个激光雷达和相机的快速且鲁棒的外参标定方法(代码开源)
  17. 关于Linux系统中文件名中带有空格问题分析
  18. 查看tomcat的端口号
  19. MyDocument.exe病毒查杀方法
  20. 计算机密码学学习笔记(二)——Shannon理论

热门文章

  1. 使用django-admin 上传-下载 文件
  2. 主流JS框架中DOMReady事件的实现
  3. 无法创建 ActiveX 组件(转载)
  4. 用sqoop从mysql导数hive_使用sqoop从mysql导入到hive基本操作
  5. C# socket编程TcpClient与TcpListener UdpClient
  6. linux里面的命令
  7. crontab定时器
  8. jvm垃圾回收机制_详解JVM内存管理与垃圾回收机制1 - 内存管理
  9. JDK安装以及配置环境变量详细步骤
  10. JSP的Listener介绍