系列文章

[Nhibernate]体系结构

[NHibernate]ISessionFactory配置

[NHibernate]持久化类(Persistent Classes)

[NHibernate]O/R Mapping基础

引言

这部分不包括大量的.NET代码例子。我们假定你已经了解如何使用.NET自身的集合类框架(.NET's collections framework)和Set集合的概念。其实如果是这样,这里就真的没有什么东西需要学习了....用一句话来做个总结,你就用你已经掌握的知识来使用他们吧。

持久化集合类(Persistent Collections)

NHibernate可以持久化以下集合的实例,包括System.Collections.IDictionary,System.Collections.IList,lesi.Collectons.ISet和任何持久实体或值的数组。类型为System.Collections.IList的属性还可以使用“bag”语义来持久。

警告:用于持久化的集合,除了集合接口外,不能保留任何实现这些接口的类所附加的语义(例如:lesi.Collectons.ListSet带来的迭代顺序iteration order)。所有的持久化集合,实际上都各自按照System.Collections.Hashtable,System.Collections.ArrayList,lesi.Collections.HashSet的语义直接工作。更深入地说,对于一个包含集合的属性来说,必须把.NET类型定义为接口(也就是IDictionary,IList或者ISet)。存在这个限制的原因是,在你不知道的时候,NHibernate暗中把你的IDictionary,IList和ISet的实例替换成了它自己的关于这些集合的实现。(所以在你的程序中,谨慎使用==操作符)

 Cat cat = new DomesticCat();
Cat kitten = new DomesticCat();
...
Iesi.Collections.ISet kittens = new Iesi.Collections.HashedSet();
kittens.Add( kitten );
cat.Kittens = kittens;
session.Save( cat );
kittens = cat.Kittens; // Okay, kittens collection is an ISet
(Iesi.Collections.HashedSet)cat.Kittens; //Error! - a NHibernate.Collections.Set not Iesi.Collections.HashedSet

集合遵从对值类型的通常规则:不能共享引用,与其包含的实体共存亡。由于存在底层的关联模型,集合不支持空值语义;

并且NHibernate不会区分一个null的集合引用和一个不存在元素的空集合。

集合类在被一个持久化对象引用的时候,会自动持久化,当不再被引用时将会自动删除。如果一个集合被从一个持久化对象传递到另一个,它的元素可能会从一个表转移到另一个表。你应该不需要对此特别关心。就如同你使用普通的 .NET集合类一样使用NHibernate的集合类,但是你需要确信使用前你理解了双向关联的语义(后面会讨论)。

集合实例在数据库中根据指向对应实体的外键而得到区别。这个外键被称为集合的关键字。在NHibernate配置文件中使用 <key> 元素来映射这个集合的关键字。

集合可以包含几乎所有的其他NHibernate类型, 包括所有的基本类型, 自定义类型,实体类型和组件。有一条重要的定义:在集合中的对象可以通过“传值”语义(完全依赖于集合自身)操作,也可以是一个指向其他实体的引用,拥有自己的生命周期。集合不能包含其他集合。这些被包含的元素的类型被称为集合元素类型。集合的元素在Hibernate中被映射为<element>, <composite-element>, <one-to-many>, <many-to-many> 或者<many-to-any>。前两种用传值语义操作元素,另外三种则映射实体关联。

除了ISet和Bag之外的所有集合类型都有一个索引(index)字段,这个字段映射到一个数组或者IList的索引或者IDictionary的key。IDictionary的索引的类型可以是任何基本类型, 实体类型或者甚至是一个组合类型(但不能是一个集合类型)。数组和IList的索引肯定是整型(Int32)。在NHibernate配置文件中使用 <index>,<index-many-to-many> ,<composite-index> 或者<index-many-to-any>等元素来映射索引。

集合类可以产生相当多种类的映射,涵盖了很多通常的关系模型。我们建议你练习使用schema生成工具, 以便对如何把不同的映射定义转换为数据库表有一个感性认识。

映射集合(Mapping a Collection)

值集合和多对多关联(Collections of Values and Many-To-Many Associations)
 一对多关联(One-To-Many Associations)

<延迟初始化(延迟加载)(Lazy Initialization)

集合排序(Sorted Collections)

使用 <idbag>

双向关联(Bidirectional Associations)

双向关联允许通过关联的任一端访问另外一端。在NHibernate中,支持两种类型的双向关联:

一对多(one-to-many):

<set>或者<bag>值在一端, 单独值(非集合)在另外一端。

多对多(many-to-many)

两端都是<set>或<bag>值

请注意NHibernate不支持带有索引的集合(IList,IDictionary或者数组)作为“多”的那一端的双向one-to-many关联,你必须使用集合或者bag映射。

要建立一个双向的多对多关联,只需要映射两个many-to-many关联到同一个数据库表中,并再定义其中的一端为inverse(使用哪一端要根据你的选择)。这里有一个从一个类关联到他自身的many-to-many的双向关联的例子(每一个category都可以有很多items,每一个items可以属于很多categories):

 <class name name="NHibernate.Auction.Category, NHibernate.Auction">
<id name="Id" column="ID"/>
...
<bag name="Items" table="CATEGORY_ITEM" lazy="true">
<key column="CATEGORY_ID" />
<many-to-many class="NHibernate.Auction.Category, NHibernate.Auction" column="ITEM_ID" />
</bag>
</class>
<class name="NHibernate.Auction.Item, NHibernate.Auction">
<id name="Id" column="ID" /> <!-- inverse end -->
<bag name="Categories" table="CATEGORY_ITEM" inverse="true" lazy="true">
<key column="ITEM_ID" />
<many-to-many class="NHibernate.Auction.Category, NHibernate.Auction" column="CATEGORY_ID" />
</bag>
</class>

如果只对关联的反向端进行了改变,这个改变不会被持久化。这表示NHibernate为每个双向关联在内存中存在两次表现,一个从A连接到B,另一个从B连接到A。如果你回想一下.NET对象模型,我们是如何在.NET中创建多对多关系的,这可以让你更容易理解:

 category.Items.Add( item ); // The category now "knows" about the relationship
item.Categories.Add( category ); // The item now "knows" about the relationship
session.Update( item ); // No effect, nothing will be saved!
session.Update( category ); // The relationship will be saved

非反向端用于把内存中的表示保存到数据库中,如果两端都进行了改变,我们会进行多余的INSERT/UPDATE,甚至可能得到外键冲突!这一点对双向的一对多关联也是一样的。
要建立一个一对多的双向关联,你可以通过把一个一对多关联,作为一个多对一关联映射到同一张表的字段上,并且在“多”的那一端定义inverse=“true”,

 <class name="Eg.Parent, Eg>
<id name="Id" column="id" />
...
<set name="Children" inverse="true" lazy="true">
<key column="parent_id" />
<one-to-many class="Eg.Child, Eg" />
</set>
</class>
<class name="Eg.Child, Eg">
<id name="Id" column="id" />
....
<many-to-one name="Parent" class="Eg.Parent, Eg" column="parent_id" />
</class>

在“一”这一端定义inverse=“true”不会影响级联操作,二者是不同的概念。

三重关联(Ternary Associations)

异类关联(Heterogeneous Associations)

总结

介绍对集合持久化,如何映射集合的方法。

本文来自《NHibernate 中文文档》

[NHibernate]集合类(Collections)映射的更多相关文章

  1. Nhibernate + MySQL 类型映射

    用SQLyog工具创建表 然后用自动映射工具NHibernate Mapping Generator对表做自动映射,得到 这个是可视化界面,后面有对应的代码. using System; using ...

  2. C++标准模板库集合类与映射类总结

    一.STL集合类 标准模板库向程序员提供了一些容器类,以便在应用程序中频繁而快速的搜索.std::set和std::multiset用于存储一组经过排序的元素,其查找元素的复杂度为对数,而unorde ...

  3. Nhibernate 一对一关系映射(主键映射)

    参考:点击这里 妈的,搞了一天了,终于可以了,现在总结下,以防下次再出现这样痛苦的问题了,有两个表:user(用户)和Blog(设置表),它们之间的关系正如我所说的是一对一的关系.现在我们来映射这两个 ...

  4. 【python】超有用的集合类collections,不来了解一下?

    在使用Python的过程中,一定是离不开数据结构的, 也就是List-列表,Tuples-元组,Dictionaries-字典. 那实际应用中我们更多的还是要去操作这些结构里的数据.比如,在列表后面添 ...

  5. NHibernate讲解

    第1章 NHibernate体系结构 总览 对NHibernate体系结构的非常高层的概览: 这幅图展示了NHibernate使用数据库和配置文件数据来为应用程序提供持久化服务(和持久化的对象). 我 ...

  6. asp.net资料! (.NET) (ASP.NET)

    使用SqlBulkCopy类加载其他源数据到SQL表 在数据回发时,维护ASP.NET Tree控件的位置 vagerent的vs2005网站开发技巧 ASP.NET2.0小技巧--内部控件权限的实现 ...

  7. HIBERNATE - 符合Java习惯的关系数据库持久化(精华篇)

    HIBERNATE - 符合Java习惯的关系数据库持久化      下一页 HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.0.4   目录 前言 1. ...

  8. [NHibernate]关联映射

    系列文章 [Nhibernate]体系结构 [NHibernate]ISessionFactory配置 [NHibernate]持久化类(Persistent Classes) [NHibernate ...

  9. [Nhibernate]SchemaExport工具的使用(一)——通过映射文件修改数据表

    目录 写在前面 文档与系列文章 SchemaExport工具 SchemaUpdate工具 一个例子 总结 写在前面 上篇文章介绍了使用代码生成器的nhibernate模版来生成持久化类,映射文件等内 ...

随机推荐

  1. linux文件拼接命令 paste

    paste [文件名1 [文件名2] --] [选项] -s 把文件以行的方式拼接 -d 制定分隔符,默认以制表符分隔 [root@dagege ~]# >.txt [root@dagege ~ ...

  2. js中取得当前加载的js的src地址

    在很多js框架中看到过,如果要动态加载框架内部的其他js,加载的时候加载的地址经常是一个相对的地址,只能是这样了哦,因为框架根本不知道用此框架的用户,将框架js文件放的具体目录,所以框架中一般会采用如 ...

  3. Maven 的classifier的作用

    直接看一个例子,maven中要引入json包,于是使用了 <dependency> <groupId>net.sf.json-lib</groupId> <a ...

  4. Ubuntu 部署 Node.js 应用

    安装Node.js环境 sudo apt-get install nodejs sudo apt-get install npm 对于不同环境依赖 的node_module可以采用以下命令来重新生成 ...

  5. Java基础知识笔记(一:修饰词、向量、哈希表)

    一.Java语言的特点(养成经常查看Java在线帮助文档的习惯) (1)简单性:Java语言是在C和C++计算机语言的基础上进行简化和改进的一种新型计算机语言.它去掉了C和C++最难正确应用的指针和最 ...

  6. nginx简易入门(转)

    相信很多人都听过nginx,这个小巧的东西慢慢地在吞食apache和IIS的份额.那究竟它有什么作用呢?可能很多人未必了解. 说到反向代理,可能很多人都听说,但具体什么是反向代理,很多人估计就不清楚了 ...

  7. COGS743. [网络流24题] 最长k可重区间集

    743. [网络流24题] 最长k可重区间集 ★★★   输入文件:interv.in   输出文件:interv.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: «编 ...

  8. CF724D. Dense Subsequence[贪心 字典序!]

    D. Dense Subsequence time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. 洛谷P3390 【模板】矩阵快速幂

    给定n*n的矩阵A,求A^k 行列都是n #include <iostream> #include <cstdio> #include <cstring> #inc ...

  10. unity 实现物体破碎效果的一些方法 - 细雨淅淅

    游戏越来越接近现实的感觉,如果有一个真是的 虚拟现实设备,可能我们真的会感觉是在真实世界.场景的逼真是在渲染效果.角色AI.游戏逻辑.物理效果等等一起导致的结果.现在游戏越来越大,除了渲染,物理估计是 ...