当前位置:主页   - 电脑 - 网站开发 - ASP.Net
NHibernate学习手记(5) - 简单的对象映射
来源:网络   作者:   更新时间:2012-08-19
收藏此页】    【字号    】    【打印】    【关闭

  本文示例源代码或素材下载

  NH的online document中讨论了三种情况的的o/r mapping:

  1)one-to-one

  2)one-to-many / many-to-one

  3)many-to-many

  因为官方文档介绍得很少,学起来非常费劲,我在这里做一个学习总结,希望能引起大家的继续讨论。

  为了便于描述。,本系列学习手记将引入Category和Item对象,分别实现以下关系:

  1)Category和Item对象之前不存在关系(none-association);

  2)Category和Item对象之前存在着one-to-many的关系,即一个Category对象对应多个Item对象;

  3)Category和Item对象之间存在着many-to-many的关系;

  4)Category和Item对象之间存在着one-to-one的关系(我认为这是最少用到的关系类型)。

  本文将以Category对象的简单操作来示例第一种情况。Category对象只有两个属性:ID(guid)和Name(string),我们来看看怎么使用NH来进行Category对象的CRUD操作。

  主要内容

  1、准备数据库

  2、编写配置文件

  3、编写POCO类

  4、Category对象的CRUD操作

  一、准备数据库

  新建数据表,对应于Category对象的属性,该数据表只有CategoryID和Name两个字段:

CREATETABLE[dbo].[nh_categories](
  [CategoryID][uniqueidentifier]NOTNULL,
  [Name][nvarchar](50)COLLATEChinese_PRC_CI_ASNOTNULL
)ON[PRIMARY]
GO

  二、编写配置文件

  nh最令我不满的一点是即使是尝试一个非常简单的crud操作,都要先编写配置文件,而且目前好像也没有很好的自动生成工具。下面让我们新建Console工程BasicMappings,编写nhibernate配置文件和xml mappings文件。

  1、新建文件hibernate.cfg.xml,并输入一下内容:

<?xmlversion="1.0"encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.0">
  <session-factoryname="CollectionMappings">
    <!--properties-->
    <propertyname="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <propertyname="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <propertyname="connection.connection_string">Server=localhost;database=NHTrial;UserId=sa;Password=sa</property>
    <propertyname="show_sql">false</property>
    <propertyname="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
    <propertyname="use_outer_join">true</property>
  </session-factory>
  
</hibernate-configuration>

  其中配置节的解释可以参考我之前发的NHibernate学习手记(3) - NH的配置信息,其中的show_sql表示是否在Console输出nh进行数据操作生成的sql语句。

  同时,因为hibernate.cfg.xml文件要求在输出目录下,还需要在[项目属性]->[通用属性]->[生成事件]->[生成后事件命令行]中添加

  copy$(ProjectDir)hibernate.cfg.xml$(TargetDir)

  用于在生成exe时把hibernate.cfg.xml文件拷贝到输出目录中。

  2、新建objects.hbm.xml文件,并把文件属性设为”嵌入资源“。NH将根据*.hbm.xml中的配置进行o/r mapping的操作。

  输入以下内容:

<?xmlversion="1.0"encoding="utf-8"?>
<hibernate-mappingxmlns="urn:nhibernate-mapping-2.0">
  <!--mappingforCategory-->
  <classname="BasicMappings.Category,BasicMappings"table="nh_categories">
    <idname="CategoryID"column="CategoryID"type="Guid">
      <generatorclass="guid"/>
    </id>
    
    <propertyname="Name"type="string"length="50"/>
  </class>
</hibernate-mapping>

NHibernate学习手记(5) - 简单的对象映射把NH源文件中包含的nhibernate-mapping-2.0.xsd文件拷贝到%.NET 2003安装目录%Common7Packagesschemasxml文件夹下,可获得intellisense的输入支持。

  1) class节点。该节点指示NH对该类的对象进行orm操作的所需的信息。

  class节点的部分重要属性含义:

AttributesUsageExample
name指示所映射类的全限定名称,格式如namespace.className.assemblyName。RequiredBasicMappings.Category, BasicMappings
table指示该类所对应的数据表名称。Requirednh_categories
schema指示所使用的数据库schema,默认继承hibernate-mappings的schema设定。NhTrial.dbo
mutable指示该类的对象可变,即nh是否可对此对象进行保存和修改的持久化操作。Optional

  其他还有lazy, persister和proxy等可选属性,在后续文章中会有介绍。

  2) id节点。id节点设定了该class的主键信息:

AttributesUsageExample
name指示对象的主键属性的名称ID
type指示该属性的NH数据类型。可选,NH可自动转换。Guid
column指示该属性对应的数据字段名称,默认取name属性值。OptionalID
unsaved-value指示该对象未保存的主键属性的取值,用于ISession.SaveOrUpdate()操作提供根据。Optional
access指示NH对该属性所采取的access-strategy和naming-strategy。默认从hibernate-mapping的default-access继承。Optionalfield.camelcase

  3)generator节点。该节点指示了主键的生成方式

classusage
identity支持DB2/MySql/MsSql/Sybase/HypersonicSql,生成整型自增id
sequence支持DB2/PostgreSql/Oracle,生成整型自增id
guid指示使用Guid.NewGuid来生成主键值
native指示根据数据类型,按照identity、sequence或hilo的方式生成主键
assigned指示主键值的设定由用户代码完成,NH无需理会

  4)property节点。该节点指示了NH进行属性映射所需要的信息:

AttributesUsageExample
name指示对象的属性名称Name
column指示该属性对应的数据列名称,默认取name属性。OptionalName
type指示该属性的NH数据类型。可选,NH可自动转换String
update指示在进行update时是否保存该属性的设置。true|false
insert指示在进行save操作时是否保存该属性的设置。true | false
formula指示该属性为表达式,将使column设置失效。ID + Name
access指示NH对该属性所采取的access-strategy和naming-strategy。默认从hibernate-mapping的default-access继承。Optionalfield.camelcase

  解释一下反复出现access设置,access=access-strategy + . + naming-strategy。

  access-trategy的取值包括:

  1)Property:默认值,NH在进行orm时将使用已定义的getter和setter来进行该属性的读取和设置。

  2)field:NH在进行orm时,将使用反射来读取和设置数据成员。

  3)nosetter:使用getter来读取属性值,使用反射方式来设置对应的数据成员。

  4) ClassName:使用指定的访问类进行属性的访问和设置,ClassName为该访问类的全限定名称。

  naming -strategy指示了在映射时,应该对name属性进行格式转换的方式。除非access-strategy为nosetter,naming- strategy为可选设置,当未设置naming-strategy时,将直接使用name属性值进行映射。下面以name=FooBar为例,看看 naming-strategy的转换后的结果:

naming-strategyexample
未设置FooBar
camelcasefooBar
camelcase-underscore_fooBar
lowercaseFoobar
lowercase-underscore_foobar
pascalcase-underscoreFooBar
pascalcase-m-underscore_FooBar

NHibernate学习手记(5) - 简单的对象映射除了上述编写xml mappings文件的方式外,NHibernateContrib库中还有通过Attribute的方式来设定orm信息的方式,在后续文章中会有介绍。

  三、编写POCO类

  POCO类的说明可参考我之前发的NHibernate学习手记(4) - 持久化类(Persistent class)的设计。

  新建类Category.cs,内容如下:

1usingSystem;
2
3namespaceBasicMappings
4{
5  ///<summary>
6  ///Category的摘要说明
7  ///</summary>
8  ///创建人:Aero
9  ///创建日期:2006-3-17
10  ///修改人:
11  ///修改日期:
12  ///修改内容:
13  ///版  本:
14  publicclassCategory
15  {
16    privateGuid_categoryId;
17
18    privatestring_name=string.Empty;
19
20    publicGuidCategoryID
21    {
22      get{returnthis._categoryId;}
23      set{this._categoryId=value;}
24    }
25
26    publicstringName
27    {
28      get{returnthis._name;}
29      set{this._name=value;}
30    }
31
32    #region构造函数
33    ///<summary>
34    ///默认无参构造函数
35    ///</summary>
36    ///创建人:Aero
37    ///创建日期:2006-3-17
38    ///修改人:
39    ///修改日期:
40    ///修改内容:
41    publicCategory()
42    {
43
44    }
45    
46    #endregion
47  }
48}
49

  四、Category对象的CRUD操作

  本文将演示如何保存随机生成的Category对象,和如何实现对象的查询。简单的CRUD操作可参考NHibernate学习手记(1) - 对象的简单CRUD操作 。新建文件Programm.cs:

1、保存Category对象
1staticreadonlyISessionFactory_factory;
2
3staticISessionFactoryFactory
4{
5  get{returnProgramm._factory;}
6}
7
8///<summary>
9///initializing
10///</summary>
11staticProgramm()
12{
13  Configurationcfg=newConfiguration().Configure();
14  cfg.AddAssembly("BasicMappings");
15
16  //initializefactory
17  Programm._factory=cfg.BuildSessionFactory();
18}
19
20///<summary>
21///savetransientobject
22///</summary>
23///<paramname="persistentObj"></param>
24staticvoidSave(objectpersistentObj)
25{
26  using(ISessionsession=Programm.Factory.OpenSession())
27  {
28    ITransactiontrans=session.BeginTransaction();
29
30    try
31    {
32      session.Save(persistentObj);
33      trans.Commit();
34    }
35    catch
36    {
37      trans.Rollback();
38      throw;
39    }
40  }
41}

  1)line13-18,初始化Configuration和SessionFactory。line13中的

  Configurationcfg=newConfiguration().Configure();

  将根据hibernate.cfg.xml文件的配置创建Congfiguration对象,但它并不知道任何orm信息。我们可以通过以下几种方式给Configuration对象提供o/r mapping的信息:

  A、通过Configuration.AddAssembly(assemblyName),nh将自动查找所制定程序集中的所有*.hbm.xml嵌入文件获取o/r mapping信息

  cfg.AddAssembly("BasicMappings");

  B、通过Configuration.AddType(Type t),nh将自动查找当前程序集中名为typeName.hbm.xml的嵌入文件该类的o/r mapping信息

  cfg.AddClass(typeof(Category));

  C、通过Configuration.AddXmlFile(fileName),nh将自动查找当前程序集中名为fileName的嵌入文件,获取o/r mapping信息

  cfg.AddXmlFile("objects.hbm.xml");

  2)line24-41,保存对象。NH中进行对象的save/update/delete操作时都必须打开事务,推荐使用using的方式来使用ISession对象。

  2、查询全部对象

1///<summary>
2///listallcategoryobjectsintherepository
3///</summary>
4staticvoidListCategory()
5{
6  using(ISessionsession=Programm.Factory.OpenSession())
7  {
8    IListcategories=session.CreateCriteria(typeof(Category)).List();
9
10    foreach(Categorycategoryincategories)
11    {
12      Console.WriteLine(category.CategoryID+""+category.Name);
13    }
14  }
15}

  3、删除全部对象

  作为一种好习惯,我们在示例代码的开始前和结束后都应该清空所添加的临时数据:)

1///<summary>
2///removeallcategoryobjectsfromtherepository
3///</summary>
4staticvoidClear()
5{
6  using(ISessionsession=Programm.Factory.OpenSession())
7  {
8    ITransactiontrans=session.BeginTransaction();
9
10    try
11    {
12      session.Delete("fromCategory");
13      trans.Commit();
14    }
15    catch
16    {
17      trans.Rollback();
18      throw;
19    }
20  }
21}

  在删除所有Category对象时,我们用了一小段HQL代码“from Category”,在后续的文章里会有介绍。

  完整的代码可从下载:ObjectsMapping.rar,其中的ExtendedCategory示例了更多的ISession的操作。

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明