这篇文章主要是对我们第一范例程序的解释和扩展。对照本篇文章,应该可以给几乎所有的简单实体编写映射文件了.
首先定义一下 简单实体是指:
1.实体和其他实体没有关系.
2.实体没有参与继承和派生.
3.实体不包含有组件.
也就是说实体是由基本类型直接构成的。这是实体是所有其它实体的基础.实际上简单实体加上和其它实体的关联关系,构成了实体类型的主体.
我们首先将前文的xml文件复制过来 然后逐行解释.遇到需要扩展的地方再扩展. Product.hbm.xml内容为:
L1:申明这是一个xml文件,为了将实体类持久化到数据库中,必须要以某种方式让NHiberante知道实体类和数据库中表的对应关系,实体类的Property或者Field和数据库表的字段的对应关系.这种关系可以通过好几种方式来表达出来。通常我们采用xml配置文件来表达.
L2:当采用xml配置文件来表达的时候,配置文件的根节点为hibernate-mappingx,xmlns定义了hibernate-mapping这个element的数据类型(xml上下文中的数据类型和C#等无关).在指定了xmlns后 基本上有两个作用:1)比较智能的IDE能够更具xmlns给出智能感知提示,在程序员编写配置文件的时候,提示可用的element,attribute或者attribute可用的值等信息.2)分析程序在开始分析该xml文件前,可以使用validator程序验证xml是否符合其定义的要求.要知道xml文件是一个文本文件,很容易就写出不符合要求的文档来.validator对xml内容的验证,类似于C#代码的编译过程中,C#编译器检查我们的代码是否符合C#语法.
2.1 assembly 属性.该属性指定了配置文件中所引用的非标准类所在的程序集.在本文档中取值为HowToNH,说明映射文件中出现的非标准类,例如Product类是存在于HowToNH这个dll中的.如果不指定assebmly,NHibernate就不知道到那个程序集中去找你的实体类了.
2.2 namespace属性.该属性指定了配置文件中所引用的非标准类所在的名字空间,本文档中的取值为HowToNH.POCO,我们可以看到在Product.cs中就有namespace HowToNH.POCO.这两个是一致的.告诉NHibernate在Product前加上HowToNH.POCO这个名字空间来作为Product这个类的全名,避免名字冲突.
L4:class结点表示一个实体类的映射.其属性name表示实体类的名称,我们这里使用的类的简单名称是因为我们已经制定了namespace=”HowToNH.POCO".table表示的是数据库中用于存储这个实体的表的名字.class 结点还有很多其它的属性可用于更详细地指定NHibernate操作实体类的方式.参考下面的说明:
在下面我将会使用L4.1来引用上述文件中标记为(1)的行,其它行类似.
L4.1和L4.2已经说过了,在大部分时候我们也只需要指定这两个属性就可以了,其它的属性都是相对高级的属性,在后面的代码中将会逐步用到.到时候都有详细的解释。这里都只做简单说明:
L4.3 discriminator-value,这个选线在实体之间有继承和派生关系的时候才使用.有时候基类和派生类的属性其实是在一张表中的,或者共同的属性是存在基类的表中的.那么当NHibernate扫描到这一个Row的时候,它怎么知道这一行的数据是属于基类的还是派生类的,如果派生了好几次,那么具体是属于哪个派生类呢?对不同的类型,给discriminator-value指定不同的值,NHibernate就可以识别出来了. 具体使用方式到解释实体继承与派生是再做说明.
L4.4 mutable 含义是可变的/易变的,默认为true,暗示该实体类的对象是可以被修改的,需要track其状态.
L4.5 schema 在数据库中对应的表属于哪个schema,对于SQL Server就是类似于dbo这样的角色,对于Oracle就是用户名.
L4.6 proxy 代理接口.如果你不直接去处理某件事,而是委托其他人去做.那么 被你委托的人就是你的代理.在NHibernate中,实体可以首先以代理的形式构造出来,也就是说NHibernate返回给客户端的实体有时候不是我们写的那个Product类的实例(当然也可能是Product的实例),这时候它返回的就是代理对象.NHibernate是允许程序员介入这个过程的.通过提供自己的代理类,就能控制实体的实例化过程.由于有可能使用代理,所以我们的Product类的所有属性都是virtual的.因为代理都是从对应的实体类派生的.
L4.7dynamic-update 是否动态更新。实际上应该解释为是否动态生成update的sql语句才对.NHibernate在默认的情况下。在编译mapping文件的时候就会给每个实体类生成insert,update和delete的sql语句.那NHibernate怎么知道你更新了哪些属性呢?答案是不知道.所以NHibernate会更新所有的字段.对于那些没有被修改的字段,其数值也会被update到数据库中去.这中操作方式能够节省track每个字段变化的时间,也能节省构造sql的时间.但是也容易出现问题,比如丢失更新之类的。所以NHibernate允许你指定是否每次动态生成update sql语句。这样就可以只更新被客户端修过过的字段而不是全部更新.
L4.8 dynamic-insert 类似dynamic-update 只不过处理的是insert的情况.
L4.9 select-before-update 在更新数据前首先select一下对象。为什么需要在update前select呢?就是我们在L4.7中提到的丢失更新的问题导致的. select-before-update可以在update前检查是否会出现丢失更新,如果会导致丢失更新,NHibernate就会拒绝update而抛出异常.还有就是如果一个脱管对象被附加到Session中,NHibernate也会检查是否需要真的需要update这个对象。也许这个对象和数据库中本来就是一致的.
L4.10 polymorphism 通过HQL查询的时候采用哪种多态方式.
L4.11 where 过滤条件 在查询该实体的时候会自动应用该过滤条件.
L4.12 persister 指定由谁来将该实体持久化到数据库.可用于给NHibernate添加扩展模块.
L4.13 batch-size 批量抓取的时候,每一批抓取多少个实体对象
L4.14 optimestic-lock 乐观锁机制.NHibernate采用乐观锁来管理数据.本属性可用于指定使用哪一种乐观锁机制
L4.15 lazy 该实体类是否采用延迟加载.延迟加载机制使得之需要加载实体类的Id就足以维护实体之间的关联关系.只有在需要实体的具体属性的时候才去加载该实体的属性数据.
这一篇就说到这里吧。下一篇将简要介绍id元素,然后主要介绍property的用法.