NHibernate学习手记(5) - 简单的对象映射

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两个字段:
CREATE  TABLE  [ dbo ] . [ nh_categories ]  (
    
[ CategoryID ]  [ uniqueidentifier ]  NOT  NULL  ,
    
[ Name ]  [ nvarchar ]  ( 50 ) COLLATE Chinese_PRC_CI_AS  NOT  NULL  
ON  [ PRIMARY ]
GO

二、编写配置文件
nh最令我不满的一点是即使是尝试一个非常简单的crud操作,都要先编写配置文件,而且目前好像也没有很好的自动生成工具。下面让我们新建Console工程BasicMappings,编写nhibernate配置文件和xml mappings文件。
1、新建文件hibernate.cfg.xml,并输入一下内容:
<? xml version="1.0" encoding="utf-8"  ?>
< hibernate-configuration   xmlns ="urn:nhibernate-configuration-2.0"  >
    
< session-factory  name ="CollectionMappings" >
        
<!--  properties  -->
        
< property  name ="connection.provider" > NHibernate.Connection.DriverConnectionProvider </ property >
        
< property  name ="connection.driver_class" > NHibernate.Driver.SqlClientDriver </ property >
        
< property  name ="connection.connection_string" > Server=localhost;database=NHTrial;User Id=sa;Password=sa </ property >
        
< property  name ="show_sql" > false </ property >
        
< property  name ="dialect" > NHibernate.Dialect.MsSql2000Dialect </ property >
        
< property  name ="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的操作。
输入以下内容:
<? xml version="1.0" encoding="utf-8"  ?>  
< hibernate-mapping  xmlns ="urn:nhibernate-mapping-2.0" >
    
<!--  mapping for Category  -->
    
< class  name ="BasicMappings.Category, BasicMappings"  table ="nh_categories" >
        
< id  name ="CategoryID"  column ="CategoryID"  type ="Guid" >
            
< generator  class ="guid"  />
        
</ id >
        
        
< property  name ="Name"  type ="string"  length ="50"  />
    
</ class >
</ hibernate-mapping >

把NH源文件中包含的nhibernate-mapping-2.0.xsd文件拷贝到%.NET 2003安装目录%"Common7"Packages"schemas"xml文件夹下,可获得intellisense的输入支持。

1) class节点。该节点指示NH对该类的对象进行orm操作的所需的信息。
class节点的部分重要属性含义:

Attributes

Usage

Example

name

指示所映射类的全限定名称,格式如namespace.className.assemblyNameRequired

BasicMappings.Category, BasicMappings

table

指示该类所对应的数据表名称。Required

nh_categories

schema

指示所使用的数据库schema,默认继承hibernate-mappingsschema设定。

NhTrial.dbo

mutable

指示该类的对象可变,即nh是否可对此对象进行保存和修改的持久化操作。Optional

 


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

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

Attributes

Usage

Example

name

指示对象的主键属性的名称

ID

type

指示该属性的NH数据类型。可选,NH可自动转换。

Guid

column

指示该属性对应的数据字段名称,默认取name属性值。Optional

ID

unsaved-value

指示该对象未保存的主键属性的取值,用于ISession.SaveOrUpdate()操作提供根据。Optional

 

access

指示NH对该属性所采取的access-strategynaming-strategy。默认从hibernate-mappingdefault-access继承。Optional

field.camelcase


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

class

usage

identity

支持DB2/MySql/MsSql/Sybase/HypersonicSql,生成整型自增id

sequence

支持DB2/PostgreSql/Oracle,生成整型自增id

guid

指示使用Guid.NewGuid来生成主键值

native

指示根据数据类型,按照identitysequence或hilo的方式生成主键

assigned

指示主键值的设定由用户代码完成,NH无需理会



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

Attributes

Usage

Example

name

指示对象的属性名称

Name

column

指示该属性对应的数据列名称,默认取name属性。Optional

Name

type

指示该属性的NH数据类型。可选,NH可自动转换

String

update

指示在进行update时是否保存该属性的设置。

true|false

insert

指示在进行save操作时是否保存该属性的设置。

true | false

formula

指示该属性为表达式,将使column设置失效。

ID + Name

access

指示NH对该属性所采取的access-strategynaming-strategy。默认从hibernate-mappingdefault-access继承。Optional

field.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-strategy

example

未设置

FooBar

camelcase

fooBar

camelcase-underscore

_fooBar

lowercase

Foobar

lowercase-underscore

_foobar

pascalcase-underscore

FooBar

pascalcase-m-underscore

_FooBar

 

 


除了上述编写xml mappings文件的方式外,NHibernateContrib库中还有通过Attribute的方式来设定orm信息的方式,在后续文章中会有介绍。

三、编写POCO类
POCO类的说明可参考我之前发的 NHibernate学习手记(4) - 持久化类(Persistent class)的设计
新建类Category.cs,内容如下:
 1  using  System;
 2 
 3  namespace  BasicMappings
 4  {
 5       ///  <summary>
 6       ///  Category 的摘要说明
 7       ///  </summary>
 8       ///  创 建 人: Aero
 9       ///  创建日期: 2006-3-17
10       ///  修 改 人: 
11       ///  修改日期:
12       ///  修改内容:
13       ///  版    本:
14       public  class  Category
15      {
16           private  Guid _categoryId;
17 
18           private  string  _name  =  string .Empty;
19 
20           public  Guid CategoryID
21          {
22               get  {  return  this ._categoryId; }
23               set  {  this ._categoryId  =  value; }
24          }
25 
26           public  string  Name
27          {
28               get  {  return  this ._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           public  Category()
42          {
43 
44          }
45          
46           #endregion
47      }
48  }
49 

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

1、保存Category对象
 1  static  readonly  ISessionFactory _factory;
 2 
 3  static  ISessionFactory Factory
 4  {
 5       get  {  return  Programm._factory; }
 6  }
 7 
 8  ///  <summary>
 9  ///  initializing
10  ///  </summary>
11  static  Programm()
12  {
13      Configuration cfg  =  new  Configuration().Configure();
14      cfg.AddAssembly( " BasicMappings " );
15 
16       //  initialize factory
17      Programm._factory  =  cfg.BuildSessionFactory();
18  }
19 
20  ///  <summary>
21  ///  save transient object
22  ///  </summary>
23  ///  <param name="persistentObj"></param>
24  static  void  Save( object  persistentObj)
25  {
26       using  (ISession session  =  Programm.Factory.OpenSession())
27      {
28          ITransaction trans  =  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中的
Configuration cfg  =  new  Configuration().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  ///  list all category objects in the repository
 3  ///  </summary>
 4  static  void  ListCategory()
 5  {
 6       using  (ISession session  =  Programm.Factory.OpenSession())
 7      {
 8          IList categories  =  session.CreateCriteria( typeof (Category)).List();
 9 
10           foreach  (Category category  in  categories)
11          {
12              Console.WriteLine(category.CategoryID  +  "  "  +  category.Name);
13          }
14      }
15  }

3、删除全部对象
作为一种好习惯,我们在示例代码的开始前和结束后都应该清空所添加的临时数据:)
 1  ///  <summary>
 2  ///  remove all category objects from the repository
 3  ///  </summary>
 4  static  void  Clear()
 5  {
 6       using  (ISession session  =  Programm.Factory.OpenSession())
 7      {
 8          ITransaction trans  =  session.BeginTransaction();
 9 
10           try
11          {
12              session.Delete( " from Category " );
13              trans.Commit();
14          }
15           catch
16          {
17              trans.Rollback();
18               throw ;
19          }
20      }
21  }

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

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

转载于:https://www.cnblogs.com/gooddasenlin/archive/2008/08/21/1273583.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值