Nhibernate回顾---父子关系查询 关联查询 使用HQL和Criteria API

来源:互联网 发布:excel去除相同数据 编辑:程序博客网 时间:2024/05/20 05:07

one-to-many关联查询:

一对多关联查询

1.原生SQL关联查询

在关系模型中:可以使用子表作为内连接查询Customer,像这样:

select * from Customer c inner join Order o on c.CustomerId=o.CustomerId where o.CustomerId=<id of the Customer>

使用父表作为内连接查询Order,像这样:

select * from Oder o inner join Customer c on o.CustomerId=c.CustomerId where o.OrderId=<id of the Order>

下面我们来看看在NHibernate中使用原生SQL查询。这篇来完成查询订单在orderData之后的顾客列表不同查询的写法。

public IList<Customer> UseSQL_GetCustomersWithOrders(DateTime orderDate){    return _session.CreateSQLQuery("select distinct {customer.*} from Customer {customer}"+    " inner join [Order] o on o.Customer={customer}.CustomerId where o.OrderDate> :orderDate")        .AddEntity("customer", typeof(Customer))        .SetDateTime("orderDate", orderDate)        .List<Customer>();}


2.HQL关联查询

查询订单在orderData之后的顾客列表的HQL关联查询写法:

public IList<Customer> UseHQL_GetCustomersWithOrders(DateTime orderDate){    return _session.CreateQuery("select distinct c from Customer c inner join c.Orders o  where o.OrderDate > :orderDate")        .SetDateTime("orderDate", orderDate)        .List<Customer>();}

这里使用基于面向对象的HQL,一目了然,符合面向对象编程习惯。

3.Criteria API关联查询

我们使用CreateCriteria()在关联之间导航,很容易地在实体之间指定约束。这里第二个CreateCriteria()返回一个ICriteria的新实例,并指向Orders实体的元素。在查询中子对象使用子CreateCriteria语句,这是因为实体之间的关联我们在映射文件中已经定义好了。还有一种方法使用CreateAlias()不会创建ICriteria的新实例。

这个例子返回顾客列表有重复的,不是我们想要的结果。

public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate){    return _session.CreateCriteria(typeof(Customer))        .CreateCriteria("Orders")        .Add(Restrictions.Gt("OrderDate", orderDate))        .List<Customer>();}

预过滤

使用ICriteria接口的SetResultTransformer(IResultTransformer resultTransformer)方法返回满足特定条件的Customer。上面例子中使用条件查询,观察其生成的SQL语句并没有distinct,这时可以使用NHibernate.Transform命名空间中的方法或者使用NHibernate提供的NHibernate.CriteriaUtil.RootEntity、NHibernate.CriteriaUtil.DistinctRootEntity、NHibernate.CriteriaUtil.AliasToEntityMap静态方法实现预过滤的作用。那么上面的查询应该修改为:

public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate){    return _session.CreateCriteria(typeof(Customer))        .CreateCriteria("Orders")        .Add(Restrictions.Gt("OrderDate", orderDate))        .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())        //或者.SetResultTransformer(NHibernate.CriteriaUtil.DistinctRootEntity)        .List<Customer>();}

这个例子从转换结果集的角度实现了我们想要的效果。

many-to-many:

1.原生SQL关联查询

public IList<Customer> UseSQL_GetCustomersWithOrdersHavingProduct(DateTime orderDate){    return _session.CreateSQLQuery("select distinct {customer.*} from Customer {customer}" +    " inner join [Order] o on o.Customer={customer}.CustomerId"+    " inner join OrderProduct op on o.OrderId=op.[Order]"+    " inner join Product p on op.Product=p.ProductId where o.OrderDate> :orderDate")        .AddEntity("customer", typeof(Customer))        .SetDateTime("orderDate", orderDate)        .List<Customer>();}

这里需要使用Join告诉查询如何在表之间关联。无论多么复杂的关系,我们必须在查询语句中指定返回值。这里使用AddEntity设置返回的实体。

2.HQL关联查询

public IList<Customer> UseHQL_GetCustomersWithOrdersHavingProduct(DateTime orderDate){    return _session.CreateQuery("select distinct c from Customer c ,"        + " c.Orders.elements o where o.OrderDate > :orderDate")        .SetDateTime("orderDate", orderDate)        .List<Customer>();}

因为在映射文件已经定义实体之间一对多、多对多关系,NHibernate通过映射文件知道如何去关联这些实体,我们不需要在查询语句中重复定义。这里使用查询和上一篇使用HQL关联查询语句一样,NHibernate完全可以去关联对象,实现查询订单和产品。

3.Criteria API关联查询

因为实体之间的关联我们在映射文件中已经定义好了。所以我们在查询子对象使用子CreateCriteria语句关联对象之间导航,可以很容易地在实体之间指定约束。这里第二个CreateCriteria()返回ICriteria的新实例,并指向Orders实体的元素。第三个指向Products实体的元素。

public IList<Customer> UseCriteriaAPI_GetCustomerswithOrdersHavingProduct(){    return _session.CreateCriteria(typeof(Customer))        .Add(Restrictions.Eq("Firstname","YJing"))        .CreateCriteria("Orders")        .Add(Restrictions.Gt("OrderDate",new DateTime(2008,10,1)))        .CreateCriteria("Products")        .Add(Restrictions.Eq("Name","Cnblogs"))        .List<Customer>();}
原创粉丝点击