NHibernate教程(9)一1对n关联映射
本节内容
- 引入
- NHibernate中的集合类型
- 建立父子关系
- 父子关联映射
- 结语
引入
通过前几篇文章的介绍,基本上了解了NHibernate,但是在NHibernate中映射关系是NHibernate中的亮点,也是最难掌握的技术。从这篇开始学习这些东西,我将图文结合来说明这里奥秘的知识。
前几篇,我们的例子只使用了一个简单的Customer对象。但是在客户/订单/产品的经典组合中,他们的关系非常复杂?让我们先回顾在第二篇中建立的数据模型。
在图上,我已经清晰的标注了表之间的关系,首先分析Customer和Order之间的“外键关系”或者称作“父子关系”、“一对多关系”。在分析之前先初步了解NHibernate中的集合。
NHibernate中的集合类型
NHibernate支持/定义的几种类型的集合:
Bag:对象集合,每个元素可以重复。例如{1,2,2,6,0,0},在.Net中相当于IList或者IList<T>实现。
Set:对象集合,每个元素必须唯一。例如{1,2,5,6},在.Net中相当于ISet或者ISet<T>实现,Iesi.Collections.dll程序集提供ISet集合。
List:整数索引对象集合,每个元素可以重复。例如{{1,"YJingLee"},{2,"CnBlogs"},{3,"LiYongJing"}},在.Net中相当于ArraryList或者List<T>实现。
Map:键值对集合。例如{{"YJingLee",5},{"CnBlogs",7},{"LiYongJing",6}},在.Net中相当于HashTable或者IDictionary<Tkey,TValue>实现。
实际上,我们大多数情况下使用Set集合类型,因为这个类型和关系型数据库模型比较接近。
建立父子关系
直接看下面一幅图的两张表:
上面两张表关系表达的意思是:Customer有一个或多个Orders,Orders属于一个Customer。一般而言,我们称Customer为“父”,Order称为“子”。Customer和Order之间关系就有几种说法:“外键关系”、“父子关系”、“一对多关系”都可以。
1.Customer有一个或多个Orders
在对象模型中:在Customer类中把Orders作为一个集合,这时可以说Customer对象包含了Orders集合。在.NET中通常这样表述:
public class Customer
{
//......
public IList<Order> Orders{ get; set; }
}
访问对象方式:通过子集合访问:Customer.Orders[...]
在NHibernate中,通常而言使用Iesi.Collections.dll程序集中的ISet集合,现在修改Customer.cs类,首先需要引用这个程序集,Customer.cs类代码如下:
using Iesi.Collections.Generic; namespace DomainModel.Entities
{
public class Customer
{
public virtual int CustomerId { get; set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
//一对多关系:Customer有一个或多个Orders
public virtual ISet<Order> Orders { get; set; }
}
}
2.Order属于一个Customer
在对象模型中:在Order类中把Customer作为单一对象,这时可以说Order对象包含了一个Customer。在.NET中通常这样表述:
public class Order
{
//......
public Customer Customer{ get; set; }
}
其访问对象方式:通过父对象成员访问:Order.Customer
我们在项目DomainModel层的Entities文件夹中新建Order.cs类,编写代码如下:
namespace DomainModel.Entities
{
public class Order
{
public virtual int OrderId { get; set; }
public virtual DateTime OrderDate { get; set; }
//多对一关系:Orders属于一个Customer
public virtual Customer Customer { get; set; }
}
}
好了,我们现在完成持久类了,下面看看这两个类如何映射。
父子关联映射
在NHibernate中,我们可以通过映射文件来关联对象之间的关系。映射文件定义了:
- 对象之间关系:一对一、一对多、多对一、多对多关系。
- 在关系中控制级联行为(Cascade behavior):级联更新、级联删除
- 父子之间的双向导航(bidirectional navigation)
1.父实体映射
父实体(Customer)映射定义了:
- 集合类型(Bag、Set、List、Map)
- 在保存、更新、删除操作时的级联行为
- 关联的控制方向:
- Inverse="false"(默认):父实体负责维护关联关系
- Inverse="true":子实体负责维护关联关系
- 与子实体关联的关系(一对多、多对一、多对多)
这些具体的设置是NHibernate中的难点所在,以后慢慢讨论这些不同设置下的奥秘之处。
这一篇初步建立Customer与Order的一对多关系,修改Customer.hbm.xml映射文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DomainModel" namespace="DomainModel"> <class name ="DomainModel.Entities.Customer,DomainModel"
table="Customer">
<id name="CustomerId" column="CustomerId" type="Int32"
unsaved-value="0">
<generator class ="native"></generator>
</id>
<property name="Firstname" column ="Firstname" type="string"
length="50" not-null="false"/>
<property name ="Lastname" column="Lastname" type="string"
length="50" not-null="false"/>
<!--一对多关系:Customer有一个或多个Orders-->
<set name="Orders" table="`Order`" generic="true" inverse="true">
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="DomainModel.Entities.Order,DomainModel"/>
</set>
</class>
</hibernate-mapping>
可以看到,在“父”端映射使用Set元素,标明属性名称、表名、子实体负责维护关联关系。
2.子实体映射
子实体(Order)映射定义的东西就是父实体少了:与父实体关联的(多对一、一对多、多对多) 关系,并用一个指针来导航到父实体。
在“子”端通过many-to-one元素定义与“父”端的关联,从“子”端角度看这种关系模型是多对一关联(实际上是对Customer对象的引用)。下面看看many-to-one元素映射属性:
看看这些映射属性具体有什么意义:
- access(默认property):可选field、property、nosetter、ClassName值。NHibernate访问属性的策略。
- cascade(可选):指明哪些操作会从父对象级联到关联的对象。可选all、save-update、delete、none值。除none之外其它将使指定的操作延伸到关联的(子)对象。
- class(默认通过反射得到属性类型):关联类的名字。
- column(默认属性名):列名。
- fetch(默认select):可选select和join值,select:用单独的查询抓取关联;join:总是用外连接抓取关联。
- foreign-key:外键名称,使用SchemaExport工具生成的名称。
- index:......
- update,insert(默认true):指定对应的字段是否包含在用于UPDATE或INSERT 的SQL语句中。如果二者都是false,则这是一个纯粹的 “外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他特性得到或者通过触发器其他程序得到。
- lazy:可选false和proxy值。是否延迟,不延迟还是使用代理延迟。
- name:属性名称propertyName。
- not-found:可选ignore和exception值。找不到忽略或者抛出异常。
- not-null:可选true和false值。
- outer-join:可选auto、true、false值。
- property-ref(可选):指定关联类的一个属性名称,这个属性会和外键相对应。如果没有指定,会使用对方关联类的主键。这个属性通常在遗留的数据库系统使用,可能有外键指向对方关联表的某个非主键字段(但是应该是一个唯一关键字)的情况下,是非常不好的关系模型。比如说,假设Customer类有唯一的CustomerId,它并不是主键。这一点在NHibernate源码中有了充分的体验。
- unique:可选true和false值。控制NHibernate通过SchemaExport工具生成DDL的过程。
- unique-key(可选):使用DDL为外键字段生成一个唯一约束。
我们来建立“子”端到“父”端的映射,新建Order.hbm.xml文件,编写代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DomainModel" namespace="DomainModel"> <class name="DomainModel.Entities.Order,DomainModel" table="`Order`" >
<id name="OrderId" column="OrderId" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="OrderDate" column="OrderDate" type="DateTime"
not-null="true" />
<!--多对一关系:Orders属于一个Customer-->
<many-to-one name="Customer" column="Customer" not-null="true"
class="DomainModel.Entities.Customer,DomainModel"
foreign-key="FK_CustomerOrders" />
</class>
</hibernate-mapping>
关于如何关联看看上面的属性就一目了然了。
结语
这一篇建立Customer和Order之间一对多关联关系,并初步了解NHibernate中的集合。下一篇继续以这一篇为基础,一步一步去挖掘,这是我一贯写法,介绍在NHibernate中使用原生SQL、HQL、Criteria API三种查询方式来关联查询。当然了,从这篇开始,研究的东西就更多了,像查询、加载机制、代理机制、再议并发控制、NHibernate提供的有用类等等。
NHibernate教程(9)一1对n关联映射的更多相关文章
- NHibernate教程
NHibernate教程 一.NHibernate简介 在今日的企业环境中,把面向对象的软件和关系数据库一起使用可能是相当麻烦.浪费时间的.NHibernate是一个面向.Net环境的对象/关系数据库 ...
- 通俗易懂的Nhibernate教程(2) ---- 配置之Nhibernate配置
在上一个教程中,我们讲了Nhibernate的基本使用!So,让我们回顾下Nhibernate使用基本的步骤吧 1.NHibernate配置 ----- 这一步我们告诉了Nhibernate:数据库 ...
- NHibernate教程(13)--立即加载
本节内容 引入 立即加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过上一篇的介绍,我们知道了NHibernate中默认的加载机制--延迟加载.其本质就是使用GoF23中代理模式 ...
- NHibernate教程(12)--延迟加载
本节内容 引入 延迟加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过前面文章的分析,我们知道了如何使用NHibernate,比如CRUD操作.事务.一对多.多对多映射等问题,这 ...
- NHibernate教程(8)--巧用组件
本节内容 引入 方案1:直接添加 方案2:巧用组件 实例分析 结语 引入 通过前面7篇的学习,有点乏味了~~~这篇来学习一个技巧,大家一起想想如果我要在Customer类中实现一个Fullname属性 ...
- Mybatis的关联映射
实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系.针对多表之间的操作,MyBatis提供了关联映射, 通过关联映射就可以很好的处理对象与对象之间的关联关 ...
- Hibernatel框架关联映射
Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...
- hibernate多对多关联映射
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Hibernate一对多单向(双向)关联映射
(1).编写配置文件 Hibernate通过读写默认的XML配置文件hibernate.cfg.xml加载数据库配置信息.代码如下: <hibernate-configuration> & ...
随机推荐
- 基于FPGA的Uart接收图像数据至VGA显示
系统框图 前面我们设计了基于FPGA的静态图片显示,接下来我们来做做基于FPGA的动态图片显示,本实验内容为:由PC端上位机软件通过串口发送一幅图像数据至FPGA,FPGA内部将图像数据存储,最后扫描 ...
- cve-2017-0199&metasploit复现过程
CVE-2017-0199 WORD/RTF嵌入OLE调用远程文件执行的一个漏洞.不需要用户交互.打开文档即中招 首先更新msf到最新,据说最新版简化了利用过程,不需要开启hta这一步.但没测成功 还 ...
- Vue模板内容
前面的话 如果只使用Vue最基础的声明式渲染的功能,则完全可以把Vue当做一个模板引擎来使用.本文将详细介绍Vue模板内容 概述 Vue.js使用了基于HTML的模板语法,允许声明式地将DOM绑定至底 ...
- PAT (Basic Level) Practise (中文)-1021. 个位数统计 (15)
1021. 个位数统计 (15) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个k位整数N = dk-1 ...
- .NET Core资源汇总
前言 首先庆祝.NET Core 2.0今天发布. 最近一两年.NET的关注度直线下降, 大部分开发人员转去了其他平台, 国内的机会也越来越少了. 行情虽然如此, 仍在坚守.NET平台的开发人员还是要 ...
- Thinkphp5 实现悲观锁
悲观锁介绍(百科): 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态.悲观锁的实现,往往依 ...
- angular学习(六)-- Filter
2.6 过滤器:Filter 内置过滤器 currency number date json uppercase lowercase orderBy limitTo filter 自定义过滤器
- python学习之字符串(下)
----------------------------------------------实际应用中的其他常见的字符串方法 >>>line = "the knights ...
- linux 网络编程
linux网络编程中主要分为服务器和客户端两部分,而网络编程中又分为TCP和UDP两种.TCP(传输控制协议)和UDP(用户数据报协议是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. ...
- 【Ubuntu 16】DEB软件包管理
一.背景介绍 开源软件最早的时候没有软件包和软件包管理器,用户只能下载源码包自行配置 编译 安装. 后来linux各发行版本推出了软件包格式和软件包管理程序 Red Hat.Centos使用RPM格式 ...