代码生成工具来生成XML配置文档。下面是一个映射的例子:
#001 <?xml version="1.0" ?>
#002 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="Eg" assembly="Eg">
#003 <class name="Cat" table="CATS" discriminator-value="C">
#004 <id name="Id" column="uid" type="Int64">
#005 <generator class="hilo"/>
#006 </id>
#007 <discriminator column="subclass" type="Char"/>
#008 <property name="Name" type="Char"/>
#009 <property name="Color" not-null="false"/>
#010 <property name="Sex" not-null="false" update="false"/>
#011 <property name="Weight"/>
#012 <many-to-one name="Mate" column="mate_id"/>
#013 <set name="Kittens">
#014 <key column="mother_id"/>
#015 <one-to-many class="Cat"/>
#016 </set>
#017 <subclass name="DomesticCat" discriminator-value="D">
#018 <property name="Name" type="String"/>
#019 </subclass>
#020 </class>
#021 </hibernate-mapping>
所有的XML映射都需要使用nhibernate-mapping-2.0 schema。目前的schema可以在NHibernate的资源路径或者是NHibernate.dll的嵌入资源(Embedded Resource)中找到。NHibernate总是会优先使用嵌入在资源中的schema文件。在使用VisualStudio.NET时,用户应该将 hibernate-mapping拷贝到C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/ Packages/schemas/xml路径中,以获得智能感知功能。
#002行:hibernate-mapping这个元素包括4个可选的属性。schema属性,指明了这个映射所引用的表所在的schema名称。假若指定了这个属性,表名会加上所指定的schema的名字扩展为全限定名。假若没有指定,表名就不会使用全限定名。default-cascade指定了未明确注明cascade属性的属性和集合类会采取什么样的默认级联风格。 auto-import属性默认在查询语言中可以使用非全限定名的类名。default-access告诉用户怎么访问属性值。假若有两个持久化类,它们的非全限定名是一样的,应该设置auto-import= "false"。假若把一个“import”过的名字同时对应两个类,NHibernate会抛出一个异常。
#003行:使用class元素来定义一个持久化类。name是持久化类(或者接口)的全限定名。table是对应的数据库表名。discriminator-value(可选 - 默认和类名一样)是一个用于区分不同的子类的值,在有多态行为时使用。
#004行:使用id来标识主键字段,因为被映射的类必须声明对应数据库表主键字段。大多数类有一个属性,为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。
#005行:必须声明的 <generator> 子元素是一个.NET类的名字,用来为该持久化类的实例生成唯一的标识。其中hilo(高低位)使用一个高/低位算法来高效地生成Int64、Int32 或者Int16类型的标识符。给定一个表和字段(默认分别是hibernate_unique_key 和next)作为高位值的来源。高/低位算法生成的标识符只在特定的数据库中是唯一的。
#007行:在“一棵对象继承树对应一个表”的策略中,<discriminator>元素是必需的,它声明了表的识别器字段。识别器字段包含标志值,用于告知持久化层应该为某个特定的行创建哪一个子类的实例。只能使用如下受到限制的类型:String,Char,Int32,Byte,Int16,Boolean,YesNo,TrueFalse。
#008-011行:<property>元素为类声明了一个持久化的属性。name是属性的名字,type(可选)是一个NHibernate类型的名字,not-null(可选)表明这个属性是否为空,update(可选-默认为true)表明在用于UPDATE的SQL语句中是否包含这个字段。
#012行:通过many-to-one元素,可以定义一种常见的与另一个持久化类的关联。这种关系模型是多对一关联(实际上是一个对象引用)。
#013-016行:<set>为集合类标识,其中discriminator-value(可选 - 默认为类名)用于区分每个独立的子类的值。
#017行:子类(subclass),多态持久化需要为父类的每个子类都进行声明。对于上面建议的“每一棵类继承树对应一个表”的策略来说,就需要使用<subclass>声明。
4.NHibernate应用实例
上面已经编写好了Cat类和相应的映射文件,为了正确调用Nhibernate,必须对web.config配置文件进行配置。具体配置代码如下:
#001 <xml version="1.0" encoding="utf-8" ?>
#002 <configuration>
#003 <configSections>
#004 <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System Version=2.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
#005 </configSections>
#006 <nhibernate>
#007 <add
#008 key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
#009 <add
#010 key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver" />
#011 <add
#012 key="hibernate.connection.connection_string"
value="server=localhost;uid=sa;pwd=123;database=Sample" />
#013 <add
#014 key="hibernate.connection.isolation" value="ReadCommitted" />
#015 <add
#016 key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
#017 </nhibernate>
#018 </configuration>
#012行:hibernate.connection.connection_string的value为连接服务器ConnectoinString。其他的都是Nhibernate运行所必需的配置信息。
配置完web.config文件,在测试工程中引用NHibernate.dll和Eg,具体代码如下。
#001 using System;
#002 using System.Collections.Generic;
#003 using System.Text;
#004 using NHibernate;
#005 using NHibernate.Cfg;
#006 using POJOLibrary;
#007 namespace Test
#008 {
#009 class Program
#010 {
#011 static void Main(string[] args)
#012 { Configuration c = new Configuration();
#013 c.AddAssembly("Eg");
#014 ISessionFactory factory = c.BuildSessionFactory();
#015 ISession s = factory.OpenSession();
#016 ITransaction t = s.BeginTransaction();
#017 Cat cat = new Cat();
#018 cat.Name = “Bolo”;
#019 cat.Color = “Black”;
#020 cat.Sex = “Male” ;
#021 cat.Weight = “12” ;
#022 s.Save(cat);
#023 t.Commit();}
#024 }
#025 }
NHibernate是通过Isession的实现类来提供功能的,上面代码通过Itransaction打开一个事务t=s.BeginTransaction(),最后通过调用t.Commit()提交事务,将数据写入数据库中。
通过上述NHibernate的一个简单的应用实例可以看到,整个应用程序中没有写任何一句SQL语句。