[NHibernate]立即加载

目录

写在前面

文档与系列文章

立即加载

一个例子

总结

写在前面

上篇文章介绍了nhibernate延迟加载的相关内容,简单回顾一下延迟加载,就是需要的时候再去加载,需要的时候再向数据库发出sql指令进行查询。

本篇文章介绍的立即加载,则和延迟加载相对,举个简单的例子,就是查询客户信息,则会将该客户相关联的数据立即进行加载。实现立即加载的方式有三种:设置映射文件中节点的可选属性lazy,Nhibernate提供的实用类,HQL抓取策略。

文档与系列文章

[Nhibernate]体系结构

[NHibernate]ISessionFactory配置

[NHibernate]持久化类(Persistent Classes)

[NHibernate]O/R Mapping基础

[NHibernate]集合类(Collections)映射 

[NHibernate]关联映射

[NHibernate]Parent/Child

[NHibernate]缓存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置与测试 

[NHibernate]HQL查询 

[NHibernate]条件查询Criteria Query

[NHibernate]增删改操作

[NHibernate]事务

[NHibernate]并发控制

[NHibernate]组件之依赖对象

[NHibernate]一对多关系(级联删除,级联添加)

[NHibernate]一对多关系(关联查询)

[NHibernate]多对多关系(关联查询)

[NHibernate]延迟加载

立即加载

一个例子

1、一对多关系

通过立即加载的方式,加载客户信息及客户的订单信息。

 1         /// <summary>
 2         /// 采用立即加载的方式加载客户信息
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public Customer GetCustomerByImmediatelyLoad(Guid customerID)
 7         {
 8             //获得ISession实例
 9             //通过using的方式将session释放,为了保证是立即加载的数据,而不是延迟加载的
10             //还记得上篇文章中提到的在延迟加载中,在关闭session情况下,再读取数据的时候就会有一个异常信息
11             //忘记的可以再回到上一篇文章进行查看
12             using (ISession session = NHibernateHelper.GetSession())
13             {
14                 return session.Get<Customer>(customerID);
15             }
16         }

1.1、修改Customer.hbm.xml文件

因为nhibernate默认是使用Lazy的方式加载数据的,也就是默认Lazy=“true”的,需要显示的指定Lazy=“false”。

1     <!--一对多关系:一个客户可以有一个或者多个订单-->
2     <!--子实体负责维护关联关系-->
3     <set name="Orders" table="TB_Order" generic="true" inverse="true" cascade="all" lazy="false">
4       <key column="CustomerID" foreign-key="FK_TB_Order_TB_Customer"></key>
5       <one-to-many class="Wolfy.Shop.Domain.Entities.Order,Wolfy.Shop.Domain"/>
6     </set>

编写一个测试验证,调用数据访问层中的使用using强制资源清理Session加载Customer对象的方法加载一个Customer对象,NHibernate这时立即加载Customer相关联的Order对象。

利用NHibernate提供实用类(NHibernateUtil)测试被关联的Customer对象集合是否已初始化(也就是已加载)。

 

上篇文章中也说明了,如果在关闭session的情况下,如果你展开customer的orders属性,就会出现异常

这也说明了Orders是跟customer一样立即加载的。

查看生成的sql语句

1 exec sp_executesql N'SELECT customer0_.CustomerID as CustomerID0_0_, customer0_.Version as Version0_0_, customer0_.CustomerName as Customer3_0_0_, customer0_.CustomerAddress as Customer4_0_0_ FROM TB_Customer customer0_ WHERE customer0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'
2
3 exec sp_executesql N'SELECT orders0_.CustomerID as CustomerID1_, orders0_.OrderID as OrderID1_, orders0_.OrderID as OrderID1_0_, orders0_.OrderDate as OrderDate1_0_, orders0_.CustomerID as CustomerID1_0_ FROM TB_Order orders0_ WHERE orders0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'

第一条sql为查询Customer的,第二条sql是查询与该customer相关联的order的。

1.2、使用NHibernateUtil实用类

NHibernate提供实用类(NHibernateUtil)可以用来检测被关联的对象集合是否已初始化,还可以强制初始化未初始化的相关联的对象。有了这个功能,我们就可以修改数据访问层中的方法,把上面使用Using强制清理关闭Session的方法中加上NHibernateUtil类提供Initialize方法来初始化Customer相关联的Order对象集合。

修改Customer.hbm.xml文件,将set节点的lazy属性设置为默认值true,或者删除该属性。

 1         /// <summary>
 2         /// NHibernateUtil方式,立即加载客户信息及关联的数据
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public Customer GetCustomerByImmediatelyLoadNHibernateUtil(Guid customerID)
 7         {
 8             //获得ISession实例
 9             //通过using的方式将session释放,为了保证是立即加载的数据,而不是延迟加载的
10             //还记得上篇文章中提到的在延迟加载中,在关闭session情况下,再读取数据的时候就会有一个异常信息
11             //忘记的可以再回到上一篇文章进行查看
12             using (ISession session = NHibernateHelper.GetSession())
13             {
14                 Customer customer = session.Get<Customer>(customerID);
15                 //
16                 // 摘要:
17                 //     Force initialization of a proxy or persistent collection.
18                 //
19                 NHibernate.NHibernateUtil.Initialize(customer.Orders);
20                 return customer;
21             }
22         }

通过该种方式,跟上面的测试结果相同,就不再贴图了。

2、多对多关系

2.1、使用Lazy=“false”属性

例子同上面的类似,就不再赘述。

2.2、使用NHibernateUtil实用类

这里采用Order和Product多对多实例进行分析。

如果想在加载Order的情况下,加载该Order下的所有Product,可以使用NHibernateUtil类初始化关联对象(把他们从数据库取出来)。

 1        /// <summary>
 2         /// NHibernateUtil方式,立即加载订单与商品
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public Order GetOrderProductByImmediatelyLoadNHibernateUtil(Guid orderId)
 7         {
 8             using (var session = NHibernateHelper.GetSession())
 9             {
10                 var order = session.Get<Wolfy.Shop.Domain.Entities.Order>(orderId);
11                 //强制初始化customer
12                 NHibernate.NHibernateUtil.Initialize(order.Customer);
13                 //强制初始化Product
14                 NHibernate.NHibernateUtil.Initialize(order.Products);
15                 return order;
16             }
17         }

测试

查看生成的sql语句

1 exec sp_executesql N'SELECT order0_.OrderID as OrderID1_0_, order0_.OrderDate as OrderDate1_0_, order0_.CustomerID as CustomerID1_0_ FROM TB_Order order0_ WHERE order0_.OrderID=@p0',N'@p0 uniqueidentifier',@p0='78A53F67-A293-48A1-BBE2-86FED77342FA'
2
3 exec sp_executesql N'SELECT customer0_.CustomerID as CustomerID0_0_, customer0_.Version as Version0_0_, customer0_.CustomerName as Customer3_0_0_, customer0_.CustomerAddress as Customer4_0_0_ FROM TB_Customer customer0_ WHERE customer0_.CustomerID=@p0',N'@p0 uniqueidentifier',@p0='B0720295-9541-40B3-9994-610066224DB8'
4
5 exec sp_executesql N'SELECT products0_.OrderID as OrderID1_, products0_.ProductID as ProductID1_, product1_.ProductID as ProductID3_0_, product1_.Name as Name3_0_, product1_.Price as Price3_0_ FROM TB_OrderProduct products0_ left outer join TB_Product product1_ on products0_.ProductID=product1_.ProductID WHERE products0_.OrderID=@p0',N'@p0 uniqueidentifier',@p0='78A53F67-A293-48A1-BBE2-86FED77342FA'

这里生成了三条sql语句,查询和Order关联的customer和Product。

2.3使用HQL抓取策略

HQL语句支持的连接类型为:inner join(内连接)、left outer join(左外连接)、right outer join(右外连接)、full join(全连接,不常用)。

“抓取fetch”连接允许仅仅使用一个选择语句就将相关联的对象随着他们的父对象的初始化而被初始化,可以有效的代替了映射文件中的外联接与延迟属性声明。

几点注意:

  • fetch不与setMaxResults() 或setFirstResult()共用,因为这些操作是基于结果集的,而在预先抓取集合时可能包含重复的数据,也就是说无法预先知道精确的行数。
  • fetch还不能与独立的with条件一起使用。通过在一次查询中fetch多个集合,可以制造出笛卡尔积,因此请多加注意。对多对多映射来说,同时join fetch多个集合角色可能在某些情况下给出并非预期的结果,也请小心。
  • 使用full join fetch 与 right join fetch是没有意义的。 如果你使用属性级别的延迟获取,在第一个查询中可以使用 fetch all properties 来强制NHibernate立即取得那些原本需要延迟加载的属性。

                                                        参考:http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html

测试代码

 1        /// <summary>
 2         /// HQL方式,立即加载订单与商品
 3         /// </summary>
 4         /// <param name="customerID"></param>
 5         /// <returns></returns>
 6         public Order GetOrderProductByImmediatelyLoadHQL(Guid orderId)
 7         {
 8             using (var session = NHibernateHelper.GetSession())
 9             {
10                 return session.CreateQuery("from Order o" +
11                     " left outer join fetch o.Products" +
12                     " inner join fetch o.Customer where o.OrderID=:orderId")
13                     .SetGuid("orderId", orderId)
14                     .UniqueResult<Order>();
15             }
16         }

生成的sql语句

总结

这篇文章介绍了nhibernate立即加载的方式,什么时候使用立即加载,什么时候使用延迟加载,视项目中的情况而定。

参考文章:http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html

博客地址: http://www.cnblogs.com/wolf-sun/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。

转载:http://www.cnblogs.com/wolf-sun/p/4082432.html

时间: 2024-11-23 05:06:13

[NHibernate]立即加载的相关文章

nhibernate数据加载之Criteria加载

加载|数据 Criteria是通过一组条件表达式(Expression)来加载数据的,它返回满足条件的对象集合. 主要接口为ICriteria,实现为CriteriaImpl类,此类加有Internal修饰,因此不能在程序集外显示创建,nhibernate在session对象中为我们提供了一个方法CreateCriteria,此方法返回ICriteria接口. 这里列出了ICriteria接口的一些方法:SetMaxResults:设置返回的最大结果数,可用于分页:SetFirstResult:

NHibernate之旅(13):初探立即加载机制

本节内容 引入 立即加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过上一篇的介绍,我们知道了NHibernate中默认的加载机制--延迟加载.其本质就是使用GoF23中代理模式实现,这节我们简单分析NHibernate另一种加载机制--立即加载.我用一张图片形象的展现立即加载机制. 立即加载 顾名思义,就是立刻加载相关联对象集合,与延迟加载相反.我们可以使用三种方法来立即加载,分别是:可选的lazy属性.NHibernate提供的实用类.HQL抓取策略.下面依次用实例分析

无法加载DLL“OraOps10.dll”: 找不到指定的模块。

问题描述 具体情况是这样的,c#开发用的是oracle10g,系统是win732位,现在部署到服务器上马windowserver200864位,oracle11g服务上面装了客户端,连接的数据服务器.用Nhibernate访问数据库正常,用引用oracle.dataaccess.client的方式访问出现无法加载DLL"OraOps10.dll":找不到指定的模块.(异常来自HRESULT:0x8007007E).按照这个帖子(http://blog.csdn.net/holyrong

Android Jni调用so库,加载库失败分析

现有一个项目,通过JNI接口调用底层库,例如:lib***.so 如下所示,总是加载不成功.调试发现,每次加载so库,会跳到catch异常处理部分,然后打印异常log信息. static{ try{ System.load("/data/data/com.***/lib/lib***.so"); } catch(UnsatisfiedLinkError ulink){ Log.i("HVnative====","Can not load library&q

Daemon Tools如何加载镜像

  首先在下载吧下虚拟光驱Daemon Tools 然后对Daemon Tools进行安装. 安装好后可以看到 右键点击该图标的DAEMON Tools Lite虚拟光驱工具. 如图 再点击装载和驱动管理. 点击出现如下图: 此时你就从这个对话框中,去找到你下载到的游戏的目录,就会发现所谓的映像文件! 游戏的映像文件格式很多种,不需要去记什么格式,只要用这个对话框去找游戏,去到下载到的游戏文件夹里, 你就会看见哪个是映像文件!若游戏只有1个映像文件,这就好办了!直接选中它,打开就是了! (强烈建

安卓viewpager加载问题

问题描述 安卓viewpager加载问题 在viewpager实现底部选项的时候,我首先进入的是首页,然后我直接点几最后一个个人中心的按钮,但是点进去的时候,他首先会想加载第二个和第三个的里面的数据,我想问下,怎么才能在点几最后一个按钮的时候,不加载第二个和第三个里面的东西,只有点击第几个就记载第几个里面的东西,这个怎么实现? 解决方案 首先先让我吐槽一下错别字,点几,还一错就错两个,是点击呀.你这个其实不应该使用viewPager而是直接使用四个fragment就行了,然后使用Fragment

给jsp页面加图片加载不出来

问题描述 给jsp页面加图片加载不出来 jsp页面在main里 图片在images里,我路径 .为啥jsp页面显示不出来呢? 解决方案 src='${request.pageContext.contextPath}/images/1.gif' 解决方案二: 解决方案三: 有木有大神 挺着急的 解决方案四: 1.先看看${request.pageContext.contextPath}对不对,一般这个不至于不正确 2.换个png等图片试试,可能是你的gif图片格式不支持,无法显示 解决方案五: 不

webview加载html,a标签超链接禁止跳转

问题描述 webview加载html,a标签超链接禁止跳转 webview加载html,a标签超链接禁止跳转 webview加载html,a标签超链接禁止跳转 webview加载html,a标签超链接禁止跳转 webview加载html,a标签超链接禁止跳转 webview加载html,a标签超链接禁止跳转 解决方案 shouldOverrideUrlLoading方法 return true 解决方案二: 简单,你在setWebViewClient()方法中把你的连接过滤掉就行了.

转圈圈定制加载中视图

// // HYCircleLoadingView.h // HYCircleLoadingViewExample // // Created by Shadow on 14-3-7. // Copyright (c) 2014年 Shadow. All rights reserved. // #import <UIKit/UIKit.h> /*! * @brief 圆形转圈圈加载等待视图 * @author huangyibiao */ @interface HYBCircleLoading