百度首页 | 百度空间
 
查看文章
 
NHibernate学习(七)
2008年04月08日 星期二 下午 02:07

2. HQL

HQL(Hibernate Query Language)是NHB的专用查询语言,它完全面向对象!就是说只需要知道对象名和属性名就可以生成HQL了,这样就再也不用去理会数据表和列了,前面说的Expression查询最终也会转换为HQL。
有两种方式来执行HQL,一种是直接使用ISession的Find方法,另一种是使用IQuery接口。IQuery接口提供了一些额外的设置,最重要的就是分页了,这个和ICriteria差不多,另外一些就是设置参数的值了。
NHB中有一组类专门用于完成数据加载,它们分别对应不同的数据加载情况,如实体加载、Criteria加载、OneToMany加载等。

下面同样以加载Customer数据为例来说明HQL的使用:
在上面的CustomerSystemFixture类中加入以下几个测试用例:
public class CustomerSystemFixture {
    [Test]
    public void LoadAllTest () {
       string query = “ from Customer “;
       IList custs = ObjectLoader.Find( query, null );
       // 根据期望的结果集写Assertion.
    }
    [Test]
    public void LoadPagerDataTest() {
       string query = “ from Customer “;
       PagerInfo pi = new PagerInfo( 0, 5 );
       IList custs = ObjectLoader.Find( query, null, pi );
    }
    [Test]
    public void LoadByName2Test() {
       string query = “ from Customer c where c.CompanyName = :CompanyName “;
       paramInfos.Add( new ParameterInfo(“CompanyName”, “test name”,        TypeFactory.GetStringType()) );
       IList custs = ObjectLoader.Find( query, paramInfos );
// 根据期望的结果集写Assertion.
    }
    [Test]
    public void LoadByNameAndAddress2Test() {
       string query = “ from Customer c where c.CompanyName = :CompanyName and c.Address = :Address“;
       paramInfos.Add( new ParameterInfo(“CompanyName”, “test name”,        TypeFactory.GetStringType()) );
       paramInfos.Add( new ParameterInfo(“Address”, “test address”, TypeFactory.GetStringType()) );
       IList custs = ObjectLoader.Find( query, paramInfos );
       // 根据期望的结果集写Assertion.
    }
}
在上面的测试用例中,我们同样将数据加载交由ObjectLoader的Find方法来处理,Find有很多重载的版本,都用于数据加载。另外还使用了一个ParameterInfo类来存储HQL语句的参数信息。
// ParamInfo
public class ParamInfo {
    private string name; // 参数名称
    private object value; // 参数值
    private IType type; // 参数类型
    public ParamInfo( string name, object value, IType type ) {
       this.name = name;
       this.value = value;
       this.type = type;
    }
    public string Name {
       get { return name; }
    }
    public object Value {
       get { return value; }
    }
    public IType Type {
       get { return type; }
    }
} //class ParamInfo

向ObjectLoader类加入以下方法:
public class ObjectLoader {
// ....
    public static IList Find( string query, ICollection paramInfos ) {
       return Find( query, paramInfos, null );
    }
    public static IList Find( string query, ICollection paramInfos, PagerInfo pi ) {
       ISession s = Sessions.GetSession();
       try {
          IQuery q = s.CreateQuery( query );
          if ( paramInfos != null ) {
             foreach ( ParamInfo info in paramInfos ) {
                if ( info.Value is ICollection )
                   q.SetParameterList( info.Name, (ICollection)info.Value, info.Type );
                else
                   q.SetParameter( info.Name, info.Value, info.Type );
             }
          }
          if ( pi != null ) {
             q.SetFirstResult( pi.FirstResult );
             q.SetMaxResults( pi.MaxResults );
          }
          return q.List();
       }
       finally {
          s.Close();
       }
    }
}
在上面的Find方法中,通过HQL语句创建一个IQuery, 然后加入参数,接着设置分页数据,最后返回列出的数据。

五 事务(没有做,自己加吧)

既然而数据库打交道,那么事务处理就是必需的,事务能保整数据完整性。在NHB中,ITransaction对象只对.NET的事务对象(实现了IDbTransaction接口的对象)进行了简单的封装。

使用NHB的典型事务处理看起来像下面这样(见ISession.cs的注释)
ISession sess = factory.OpenSession();
Transaction tx;
try {
    tx = sess.BeginTransaction();
    //do some work
    //...
    tx.Commit();
}
catch (Exception e) {
    if (tx != null) tx.Rollback();
    throw e;
}
finally {
    sess.Close();
}
事务对象由ISession的BeginTransaction取得,同时事务开始,如果执行顺利则提交事务,否则回滚事务。

当实现一个业务规则时,而这一规则要改变多个业务对象状态时,这时就需要使用事务了,事务能保证所有改变要么全部保存,要么全部不保存!

在罗斯文商贸案例中,有这样一个业务规则:
如果客户对某一产品下了订单,那么被订购产品的已订购数量(UnitsOnOrder)应该加上客户的产品订单量,根据这一业务规则,创建一个测试用例如下:

[TestFixture]
public class OrderFixture {
    [Test]
    public void OrderTest() {
       Product p = new Product();
       p.UnitsOnOdrer = 20;
       p.Create();

       Order o = new Order();

       OrderItem item = new OrderItem();
       item.Order = o;
       item.Product = p;
       item.OrderNum = 10;

       OrderCO.Create( o );

       Product p2 = new Product( p.ProductId );
       Assert.AreEqual( p2.UnitsOnOrder, 30, “add to unitsonorder fail!” );
    }
}


类别:.net开发 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu