• [NHibernate]延迟加载


    目录

    写在前面

    文档与系列文章

    延迟加载

    一个例子

    总结

    写在前面

    上篇文章介绍了多对多关系的关联查询的sql,HQL,Criteria查询的三种方式。本篇文章将介绍nhibernate中的延迟加载方式,延迟加载按个人理解也可以叫做按需要加载(Loading-on-demand)。

    文档与系列文章

    [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]多对多关系(关联查询)

    延迟加载

    延迟加载(Lazy Load)是(也成为懒加载)Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。

    延迟加载的有效期是在session打开的情况下,当session关闭后,会报异常。当调用load方法加载对象时,返回代理对象,等到真正用到对象的内容时才发出sql语句。

    Hibernate2实现延迟加载有2种方式:1实体对象,2集合。

    Hibernate3中又引入了一种新的加载方式:3属性的延迟加载。

    一般使用load的方法来实现延迟加载,在实现无限级联动使用延迟加载效率比较好。

    ——百度百科(java,hibernate)

    上面是java中对hibernate的延迟加载的描述,说的比我好多了。

    记住三点:1,为了避免无谓的性能开销。2,需要时才真正加载数据。3,使用了代理。 

    一个例子

    一对多关系

    默认延迟加载

    采用懒加载的方式根据客户id得到客户信息

     1         /// <summary>
     2         /// 采用懒加载的方式根据客户id得到客户信息
     3         /// </summary>
     4         /// <param name="customerID"></param>
     5         /// <returns></returns>
     6         public Customer GetCustomerbyLazyLoad(Guid customerID)
     7         {
     8             //获得ISession实例
     9             ISession session = NHibernateHelper.GetSession();
    10             Customer customer = session.Get<Customer>(customerID);
    11             return customer;
    12         }

     测试用代码,如图所示,此时数据已经加载出来了

    使用SQL Profile监控生成的sql语句,截图如下

     

    你会发现,此时只生成了查询customer的sql语句,nhibernate默认是使用延迟加载的,在前面的文章中,并没在映射文件中设置节点的lazy属性。

    当展开customer的属性Orders时或者调试向下移动的时候,会执行查询,你会看到如下的sql语句

    延迟加载并关闭Session

     1         /// <summary>
     2         /// 采用using释放session,懒加载的方式根据客户id得到客户信息
     3         /// </summary>
     4         /// <param name="customerID"></param>
     5         /// <returns></returns>
     6         public Customer GetCustomerbyLazyLoadUsing(Guid customerID)
     7         {
     8             //获得ISession实例
     9             using(ISession session = NHibernateHelper.GetSession())
    10             {
    11                 Customer customer = session.Get<Customer>(customerID);
    12                 return customer;
    13             }
    14         }

    测试,当视图展开customer的orders属性,或者往下执行获得order集合时出错。

    延迟加载,需要的时候再去加载,因为此时session已经关闭,没有去查询的通道了,结果是“此路不通”的提示。

    多对多关系

    默认延迟加载

    这里采用多对多关系那篇文章中举的 Order和Product的例子。

     1         /// <summary>
     2         /// 多对多关系,延迟加载订单产品
     3         /// </summary>
     4         /// <returns></returns>
     5         public Order GetOrderByLazyLoad(Guid orderId)
     6         {
     7             try
     8             {
     9                 var session = NHibernateHelper.GetSession();
    10                 return session.Get<Wolfy.Shop.Domain.Entities.Order>(orderId);
    11             }
    12             catch (Exception)
    13             {
    14                 throw;
    15             }
    16         }

    进行测试,在查询的时候只有Order表的数据(这个地方,有Order数据的sql,猜测在一对多查询的时候,没有出现查询Customer的sql语句,很有可能是因为缓存的问题造成,因为经常使用Cusomer那条数据进行测试。)

    展开Order的属性

    当展开Order的属性,回去查询order下的所有的Product,此时生成的sql如下:

    延迟加载并关闭Session

     1         /// <summary>
     2         /// 多对多关系,延迟加载订单产品
     3         /// </summary>
     4         /// <returns></returns>
     5         public Order GetOrderByLazyLoadUsing(Guid orderId)
     6         {
     7             //session使用后即释放
     8             using (var session = NHibernateHelper.GetSession())
     9             { return session.Get<Wolfy.Shop.Domain.Entities.Order>(orderId); }
    10         }

    测试

    此时生成的sql语句

    如果此时展开Products,同样会出现上面的异常

    通过上面的比较一对多和多对多的默认延迟加载和关闭session后的情况类似。

    N+1次select查询问题

    如果Order下有很多个Product,而我们就想需要的时候才去加载其中某些Product的信息,如果采用立即加载的方式,势必产生多个sql语句,例如第一次查询得到所有的Order对象,然后根据orderid去查询得到所有的产品。

    测试,多对多延迟加载订单和订单下单价大于6666的产品

     1        protected void btnMany2Many_Click(object sender, EventArgs e)
     2         {
     3             Business.OrderBusiness orderBusiness = new Business.OrderBusiness();
     4             Order order = orderBusiness.GetOrderByLazyLoad(new Guid("78A53F67-A293-48A1-BBE2-86FED77342FA"));
     5             decimal sum = 0;
     6             foreach (var item in order.Products)
     7             {
     8                 if (item.Price >= 6666)
     9                 {
    10                     sum += item.Price;
    11                 }
    12             }
    13             Response.Write(sum.ToString());
    14         }

    生成的sql语句

    延迟加载,可以解决select N+1的问题,比如你查询一个订单还有订单下的Product,势必会产生多条sql语句,先是查询order的sql语句,然后是查询product的sql语句,就会频繁的查询数据库,造成性能方面的压力,而采用延迟加载,通过上面生成的sql语句你会发现,使用left out join 将关联的表拼接起来,只生成了一条sql。

    总结

    本篇文章介绍了Nhibernate在延迟加载方面的内容,Nhibernate在使用过程中延迟加载方式是默认的。对延迟加载的定义,需要再慢慢的体会。

    延迟加载(Lazy Load)是(也成为懒加载)Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。

    延迟加载的有效期是在session打开的情况下,当session关闭后,会报异常。当调用load方法加载对象时,返回代理对象,等到真正用到对象的内容时才发出sql语句。

    Hibernate2实现延迟加载有2种方式:1实体对象,2集合。

    Hibernate3中又引入了一种新的加载方式:3属性的延迟加载。

    一般使用load的方法来实现延迟加载,在实现无限级联动使用延迟加载效率比较好。

    ——百度百科(java,hibernate)

  • 相关阅读:
    Nginx+keepalived高可用配置
    kubespahere安装kubenetes
    Fastdfs原理及集群搭建
    Spark 3.0.3集群安装文档
    Mybatis Plus 代码生成器
    redis集群方案
    Go 语言并发之道
    重构-改善即有代码的设计
    QT线程
    QT中的cout
  • 原文地址:https://www.cnblogs.com/wolf-sun/p/4077226.html
Copyright © 2020-2023  润新知