hibernate优化(一):抓取策略

抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL或者QBC中声明。

1.首先区分两个正交的概念:关联何时被抓取、关联如何被抓取

        1.1如何抓取(hibernate支持的抓取方式):

  • Join fetching:在select语句中使用外连接来获得对象的关联实例或关联集合
  • select fetching:在访问关联关系的时候发出一条sql语句获取当前对象的关联实体或集合
  • SubSelect fetching:在访问关联关系的时候发出一条sql语句获取在前面查询到(或者抓取到)的所有实体对象的关联实体或集合
  • Batch fetching:通过指定主外键列表,发送一条sql来获取多行数据(select * from users u where u.id in (?,?,?,?,?))

       1.2何时抓取(hibernate支持的方式):


2.通常使用的抓取策略(解决N+1问题的方法一)

       通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用 HQL 的左连接抓取(left join fetch) 对其进行重载。

    List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list();

       这样做使hibernate查询宿主对象时的sql语句使用outer join直接获取到了关联对象的数据

3.实例化集合和代理

        3.1首先,我们需要明确

  • 使用load()方法返回的是代理对象,使用get()方法返回的是Entity实例对象。

        3.2避免异常的措施

  • 使用静态方法
    Hibernate.initialize(c1.getTopics());   //强制抓取关联对象
  • 保证session处于open状态:

                  使用open session in view 模式

<!-- openSessionInView -->
  <filter>
  	<filter-name>OpenSessionInView</filter-name>
  	<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
  </filter>

  <filter-mapping>
  	<filter-name>OpenSessionInView</filter-name>
  	<url-pattern>/*</url-pattern>       
  </filter-mapping>

必须配置在所有Filter之前

                  在一个有单独业务层的应用中,使用Hibernate.initialize()方法在业务返回前为web准备好了所有所需要的数据


4.使用批量抓取(解决N+1问题的方法二)

      使用  @BatchSize  注解加到关联对象上

@Entity
@BatchSize(size=5)
public class Category {
......
}
这样hibernate将会采取 Batch fetching抓取策略

5.get()和load()的区别

  • get()返回的是Entity实例对象,load()返回的是代理对象
  • 当使用get()查询先找一级缓存,若没有立即发出sql语句查询;使用load()先后去一级缓存、二级缓存查找,若找不到返回代理对象,当访问对象的非id内容时发出sql
  • 当数据库中没有相应记录时,get()返回null, load() 抛出 ObjectNotFoundException

      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值