分享

Hibernate N+1问题的一种解决办法(Loadall)

 冷刃寒冰 2009-12-26

大家知道Hibernate有一个典型的Performance问题,就是N+1问题。为了解决N+1问题,大家提出了各种各样的方案。 这里也简单的描述一种N+1的解决办法。

Hibernate的原理是,

 --当使用Get时,首先先在Session中使用PK匹配查找相应的对象,如果对象存在,直接返回该对象,否则

   发行SQL语句进行数据库查询,如果数据库中不存在,则返回Null,否则返回该对象。

 --当使用Load时,首先先在Session中使用PK匹配查找相应的对象,如果对象存在,直接返回该对象,否则

   发行SQL语句进行数据库查询,如果数据库中不存在,则返回ObjectNotFound例外,否则返回该对象。

当使用二级缓存时,在当前Session不存在时,会先在二级缓存进行查找后再查找数据库。

 

由于二级缓存在使用上容易出现问题,比如绕过Hibernate直接维护数据库,集群环境等,在系统性能未成为瓶颈时一般建议是不使用,因此N+1的问题很容易发生。

 

为此,我们可以利用Hibernate的get和load原理,以及缓存原理,来进行性能改善,方法如下:

  【假设1】  需要将本月的所有订单信息导出成为Excel。 订单信息中包括经销商名称、订单状态、订单类型

          等信息。  如果不使用FetchMode=“Join”的方式或类似的方式进行处理,很容易发生N+1问题。

          即,查询出本月所有的订单信息,然后发多条Select查询经销商信息,订单状态,订单类型。

  【改善方法】

          1. 特别为Excel导出功能开发相应的DAO方法,将各子表连接进来查询。

          2. 如果经销商的信息不是特别多(数百条以内),我们可以使用Dao.LoadAll()方法将

             所有的子表数据提前加载在本会话中,这样的话,当基于各条订单信息获取经销商、订单

             状态、订单类型等信息时,虽仍然使用Get方法逐个获取,但因为事前LoadAll在本会话中

             进行了缓存,因此不会有N+1的现象发生。

  【注意事项】

          1. 考虑到数据量,不要将大数据量的信息Load到会话中进行缓存。

          2、 基于Hibernate Template请准备类似LoadAll()之类的方法。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多