1、Nhibernate测试驱动开发Nhibernate测试驱动开发本文约定:1. Nhibernate简写为NHB;2. 本文例子的开发平台为win2000xp+sp2, sql server2000, Nhibernate0.9.1.0;3. 使用SQL Server自带的罗斯文商贸数据库(Northwind),中文版;4. 本文例子是基于测试驱动开发(TDD)的,因此建议使用NUnit2.2和Log4Net (如果你不熟悉NUnit,不要紧啊,趁此机会学习点简单的应用);一 NHB简介NHB是基于的O/R Mapping持久框架,它从基于Java的Hibernate项目移植而来。O/R Ma
2、pping就是把对象到映射关系数据库的记录,简单的说就是能实现把一个对象存储为数据表中的一条记录和由一条记录创建一个相应的对象,数据表中的数据就是对象的属性。那么为什么要使用O/R Mapping?它与传统的DataSet/DataTable又有什么不同了?首先是设计上的不同,当使用O/R Mapping时,更多的是从对象的角度来设计程序,而把数据(对象的属性)存储的细节放在后面, 可以完全采用面向对象(OO)的方式来设计,而在使用DataSet/DataTable时,它只是存放数据的对象,看起来更像一个数据表,不能直观的表达业务概念。 二 NHB中主要接口的介绍ISessionISessio
3、n是面向用户的主要接口,主要用于对象持久化,数据加载等操作,支持数据库事务,它隐藏了NHB内部复杂的实现细节,ISession由ISessionFactory创建。ISessionFactoryISessionFactory是NHB内部的核心类,它维护到持久机制(数据库)的连接并对它们进行管理,同时还会保存所有持久对象的映射信息。ISessionFactory由Configuration创建,因为创建ISessionFactory的开销非常大(需要加载映射信息),所以这个对象一般使用Singleton(单例)模式。ITransactionITransaction是NHB的事务处理接口,它只是简
4、单的封装了底层的数据库事务。事务必须由ISession来启动。ICriteriaICriteria是Expression(表达式)数据加载接口,Expression是一个关系表达式组合,通过它能产生SQL语句的Where部分, 用户需要通过ISession来间接调用它。IQueryIQuery是HQL数据加载接口,HQL(Hibernate Query Language)是NHB专用的面向对象的数据查询语言,它与数据库的SQL有些类似,但功能更强大!同ICriteria一样,也需要通过ISession来间接调用它。三 持久化操作1. 会话和会话工厂要进行持久化操作,必须先取得ISession和
5、ISessionFactory,我们用一个Sessions类来封装它们, Sessions类的属性和方法都是静态的,它有一个Factory属性, 用于返回ISessionFactory, 有一个GetSession方法,用于取得一个新的ISession。测试类代码如下:style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDING-T
6、OP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededusing System; using NUnit.Framework; using NHibernate; namespace NHibernateTest / / SessionsFixture 的摘要说明。 / / TestFixture public class SessionsFixture public SessionsFixture() / / TODO: 在此处添加构造函数逻辑 / Test / 测试能否取得NHB会话工厂。 public void
7、 FactoryTest() ISessionFactory sf = Sessions.Factory; Assert.IsNotNull( sf, get sessionfactory fail! ); Test / 测试能否取得NHB会话。 public void GetSessionTest() ISession s = Sessions.GetSession(); Assert.IsNotNull( s, get session fail! ); 现在还没写Sessions类,将不能通过编译! 下面我们来实现Sessions类.style=BORDER-RIGHT: black 1p
8、x solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededusing System; using NHibernate; using System.Reflection; namespace NHibernateTest / / Sessions 的摘
9、要说明。 / public class Sessions private static readonly object lockObj = new object(); private static ISessionFactory _factory; public Sessions() / / TODO: 在此处添加构造函数逻辑 / public static ISessionFactory Factory get if ( _factory = null ) lock ( lockObj ) if ( _factory = null ) NHibernate.Cfg.Configuration
10、 cfg = new NHibernate.Cfg.Configuration (); cfg.AddAssembly( Assembly.GetExecutingAssembly() ); _factory = cfg.BuildSessionFactory(); return _factory; public static ISession GetSession() return Factory.OpenSession(); OK,现在编译可以通过了,启动NUnit并选择生成的文件NHibernateTest.exe,运行测试。我们得到了红色的条,出错了!原来还没有加入NHibernate
11、的配置信息(当使用NHibernate时,需要在项目的配置文件中加入NHibernate的配置信息。关于配置信息,在下面有说明)。在项目的配置文件App.Config(如没有请自行创建一个)中加入以下内容.稍做解释,下面的配置文件主要是配置了NHibernate和log4net,例如配置了NHibernate连接数据库的连接字符串;log4net把日志记到哪个文件中,本例就是log.txt。每次写日志向文件中追加,而不是重写style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid;
12、PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededxml version=1.0 encoding=utf-8 ? configSections nhibernate param name=ConversionPattern value=%d %t %-5p %c %x - %m%n / layout appender root log4net config
13、uration 再次运行测试,就可以看见绿色的条了。在取得会话工厂的代码中,我使用了如下代码:if ( _factory = null ) lock ( lockObj ) if ( _factory = null ) / build sessionfactory code; 这是一个典型的double lock方式,用来产生线程安全的Singletion(单例)对象。2. 基本CRUD操作在很多介绍NHB的文章,包括NHB带的测试用例中,业务对象只是做为一个数据实体存在的,它没有任何操作!这在java中是比较典型的作法。而我希望我们的业务对象自身就能完成基本的Create/Retrieve/
14、Update/Delete,即CRUD操作,在罗斯文商贸应用中,存在客户(customer)业务对象,先来为它建立一个测试用例, style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededusin
15、g System; using NHibernate; using NUnit.Framework; namespace NHibernateTest / / CustomerFixture 的摘要说明。 / TestFixture public class CustomerFixture public CustomerFixture() Test / 测试Customer对象的CRUD操作。 public void TestCRUD() Customer c = new Customer(); c.CustomerId = test; c.CompanyName = company name
16、; c.ContactName = contact name; c.Address = address; c.Create(); / 测试 insert操作, Customer c2 = new Customer( c.CustomerId ); / 测试 retrieve 操作. Assert.AreEqual( c2.CompanyName, company name, save companyname fail! ); c2.CompanyName = update name; c2.Update(); / 测试 update 操作. Customer c3 = new Customer
17、( c.CustomerId ); Assert.AreEqual( c3.CompanyName, update name, update companyname fail! ); c3.Delete(); / 测试 delete 操作. 接下来创建Customer业务类:style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDIN
18、G-TOP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededusing System; namespace NHibernateTest / / Customer 的摘要说明。 / public class Customer : BizObject public Customer() public Customer( string existingId ) : base( existingId ) #region persistent properties. private string _customerId =
19、string.Empty; private string _companyName = string.Empty; private string _contactName = string.Empty; private string _contactTitle = string.Empty; private string _address = string.Empty; private string _city = string.Empty; private string _region = string.Empty; private string _postalCode = string.E
20、mpty; private string _country = string.Empty; private string _phone = string.Empty; private string _fax = string.Empty; public string CustomerId get return _customerId; set _customerId = value; public string CompanyName get return _companyName; set _companyName = value; public string ContactName get
21、 return _contactName; set _contactName = value; public string ContactTitle get return _contactTitle; set _contactTitle = value; public string Address get return _address; set _address = value; public string City get return _city; set _city = value; public string Region get return _region; set _regio
22、n = value; public string PostalCode get return _postalCode; set _postalCode = value; public string Country get return _country; set _country = value; public string Phone get return _phone; set _phone = value; public string Fax get return _fax; set _fax = value; #endregion 在Customer类中,没有实现CRUD操作,这些操作
23、在业务对象基类BizObject中实现,代码如下:style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: black 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: #edededusing System; namespace NHibernateTest / / B
24、izObject 的摘要说明。 / public class BizObject public BizObject() public BizObject( object existingId ) ObjectBroker.Load( this, existingId ); public virtual void Create() ObjectBroker.Create( this ); public virtual void Update() ObjectBroker.Update( this ); public virtual void Delete() ObjectBroker.Delete( this ); BizObject简单的将数据操作转发至ObjectBroker类, 目的是为了降低业务层和NHB之间的耦合, 以利于持久层间的移植。style=BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 4px; BORDER-TOP: black 1px solid; PADDING-LEFT: 4px; PADDING-BOTTOM: 4px; BORDER-LEFT: bl
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1