`
一日一博
  • 浏览: 229601 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Hibernate4性能之Fetching策略

阅读更多

Hibernate有一些fetching策略,来优化Hibernate所生成的select语句,以尽可能地提高效率。在映射关系中声明fetching策略,定义Hibernate怎样获取其相关的集合和实体。

影响关系映射抓取的cfg配置:

hibernate.max_fetch_depth
为单向关联(一对一, 多对一)的外连接抓取(outer join fetch)树设置最大深度. 值为0意味着将关闭默认的外连接抓取.
取值 建议在0到3之间取值

hibernate.default_batch_fetch_size
为Hibernate关联的批量抓取设置默认数量.
取值 建议的取值为4, 8, 和16

如果你的数据库支持ANSI, Oracle或Sybase风格的外连接, 外连接抓取通常能通过限制往返数据库次数 (更多的工作交由数据库自己来完成)来提高效率. 外连接抓取允许在单个SELECTSQL语句中, 通过many-to-one, one-to-many, many-to-many和one-to-one关联获取连接对象的整个对象图.
将hibernate.max_fetch_depth设为0能在全局 范围内禁止外连接抓取. 设为1或更高值能启用one-to-one和many-to-one外连接关联的外连接抓取, 它们通过 fetch="join"来映射.

Hibernate有四种fetching策略,当同时配置了JPA的fetch时,会优先使用Hibernate的注解:
  • fetch-“join”:禁用延迟加载,总是立即加载所有的集合和实体。
  • fetch-“select”(默认):延迟加载所有的集合和实体。
  • fetch-“subselect”:将其集合组织到一个子查询语句中。
  • batch-size=”N”:获取上限为“N”个的集合或实体,没有记录。


在XML映射文件中声明fetch策略:
...
<hibernate-mapping>
  <class name="com.java.demo.Stock" table="stock">
    <set name="stockDailyRecords" cascade="all" inverse="true"
        table="stock_daily_record" batch-size="10" fetch="select">
      <key>
        <column name="STOCK_ID" not-null="true" />
      </key>
      <one-to-many class="com.java.demo.StockDailyRecord" />
    </set>
  </class>
</hibernate-mapping>


以标注的形式声明fetch策略:
...
@Entity
@Table(name = "stock")
public class Stock implements Serializable{
...
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
  @Cascade(CascadeType.ALL)
  @Fetch(FetchMode.SELECT)
  @BatchSize(size = 10)
  public Set<StockDailyRecord> getStockDailyRecords() {
    return this.stockDailyRecords;
  }
...
}



下面探讨fetch策略如何影响到Hibernate生成的SQL语句
1、@Fetch(FetchMode.SELECT)
另外发送一条SELECT语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
这是默认的fetch策略。请看示例代码:

  //call select from stock
  Stock stock = (Stock)session.get(Stock.class, 114);
  Set sets = stock.getStockDailyRecords();
 
  //call select from stock_daily_record
  for ( Iterator iter = sets.iterator();iter.hasNext(); ) {
    StockDailyRecord sdr = (StockDailyRecord) iter.next();
    System.out.println(sdr.getDailyRecordId());
    System.out.println(sdr.getDate());
  }

输出如下:
Hibernate:
  select ...from demo.stock
  where stock0_.STOCK_ID=?
 
Hibernate:
  select ...from demo.stock_daily_record
  where stockdaily0_.STOCK_ID=?

2、@Fetch(FetchMode.JOIN)
“join”类型fetch策略将禁用延迟加载所有相关的集合。Hibernate通过在SELECT语句使用OUTER JOIN(外连接)来获得对象的关联实例或者关联集合。
执行上面的代码输出如下:

Hibernate:
  select ...
  from
    demo.stock stock0_
  left outer join
    demo.stock_daily_record stockdaily1_
    on stock0_.STOCK_ID=stockdaily1_.STOCK_ID
  where
    stock0_.STOCK_ID=?

Hibernate只生成一个select语句,当Stock被初始化时,它获取所有其相关的集合。

3、@Fetch(FetchMode.SUBSELECT)
Fetching策略能够将其所有相关集合放在一个子select语句中。
另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
当通过Query等接口查询多个实体时,如果指定fetch="subselect"则将通过子查询获取集合
还是运行上面代码输出:

Hibernate:
  select ...
  from demo.stock stock0_
 
Hibernate:
  select ...
  from
    demo.stock_daily_record stockdaily0_
  where
    stockdaily0_.STOCK_ID in (
      select
        stock0_.STOCK_ID
      from
        demo.stock stock0_
    )

4、@BatchSize(size=10)
对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。  
当通过Query等接口查询多个实体时,如果指定farm的batch-size="……"则将通过使用单条SELECT语句获取一批对象实例或集合。
可指定全局批量抓取策略: hibernate.default_batch_fetch_size,取值:建议的取值为4, 8, 和16。
执行上面代码输出如下:

Hibernate:
  select ...from demo.stock
  where stock0_.STOCK_ID=?
 
Hibernate:
  select ...from demo.stock_daily_record
  where stockdaily0_.STOCK_ID=?

batch-size什么也没做。请看下面的解释:
batch-size fetching策略并不是定义集合中有多少记录被预加载。相反,它其实是定义有多少集合应该被加载。

  List<Stock> list = session.createQuery("from Stock").list();
  for(Stock stock : list){
    Set sets = stock.getStockDailyRecords();
    for ( Iterator iter = sets.iterator();iter.hasNext(); ) {
      StockDailyRecord sdr = (StockDailyRecord) iter.next();
      System.out.println(sdr.getDailyRecordId());
      System.out.println(sdr.getDate());
    }
  }

没有batch-size fetching策略时,输出:
Hibernate:
  select ...
  from demo.stock stock0_
 
Hibernate:
  select ...
  from demo.stock_daily_record stockdaily0_
  where stockdaily0_.STOCK_ID=?
 
Hibernate:
  select ...
  from demo.stock_daily_record stockdaily0_
  where stockdaily0_.STOCK_ID=?
 
继续重复select语句....这取决于数据表中有多少条stock记录。

如果在数据库中有20条股票记录,Hibernate默认的fetching策略将生成20+1个select语句,这将对数据库造成一定的冲击。

启用batch-size=”10” fetching策略时,输出:

Hibernate:
  select ...
  from demo.stock stock0_
 
Hibernate:
  select ...
  from demo.stock_daily_record stockdaily0_
  where
    stockdaily0_.STOCK_ID in (
      ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
    )

现在,Hibernate将预提取集合,使用select in语句。如果在数据库中有20条股票记录,Hibernate将生成3个select语句

抓取优化

集合N+1:
可以使用batch-size来减少获取次数,即如batch-size=”10”,则是N/10+1。
开启二级缓存。
对于集合比较小且一定会用到的可采用fetch=”join”,这样只需一条语句。

结论

Fetching策略非常具有弹性,是一个优化Hibernate查询的非常重要的技巧。不过如果用在错误的地方,那将会是一个灾难。
分享到:
评论

相关推荐

    hibernate-性能优化

    【标题】:优化 Hibernate 性能的关键策略 【描述】:在使用 Hibernate 进行数据库操作时,性能问题时常出现,但通过适当的调整和优化,我们可以显著提高 Hibernate 的执行效率,甚至达到接近或超过直接使用 JDBC ...

    Hibernate提升性能Hibernate提升性能

    因此,平衡延迟加载和立即加载的使用,结合合适的批量抓取策略,是提高Hibernate性能的关键。 总的来说,理解并熟练运用Hibernate的抓取策略,能够帮助开发者创建更高效的数据访问层,降低系统开销,从而提升整体...

    Hibernate性能优化

    《Hibernate性能优化》 ...以上是Hibernate性能优化的一些核心点,实践中还需要结合具体项目进行调整和测试,找到最适合的优化策略。学习和理解这些知识点,有助于开发出更高效、更稳定的Java应用程序。

    如何提高hibernate性能

    【提高Hibernate性能】 在开发大型企业级应用时,ORM框架如Hibernate在处理大量数据时可能会出现性能瓶颈。针对这种情况,优化Hibernate的配置和使用策略至关重要。以下是一些提高Hibernate性能的关键点: 1. **...

    hibernate抓取策略和懒加载案例

    在Java的持久化框架Hibernate中,数据访问优化...总的来说,选择合适的抓取策略和恰当使用懒加载是优化Hibernate应用性能的重要手段。开发者应根据业务场景灵活运用,平衡内存消耗与数据库交互,以达到最佳的性能表现。

    Hibernate性能优化共9页.pdf.zip

    《Hibernate性能优化共9页.pdf》的压缩包文件聚焦于Java开发中的一个重要框架——Hibernate的性能调优。Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作,但同时也可能带来性能问题。以下...

    day36 06-Hibernate抓取策略:set集合上的抓取策略

    为了解决这个问题,Hibernate提供了多种抓取策略,如Eager Loading(急加载)、Batch Fetching(批量加载)和Subselect Fetching(子查询加载)等。 1. Eager Loading:急加载是一种在加载主对象时同时加载其关联...

    hibernate面试题大全

    在Hibernate中,针对关联对象的检索,有三种主要的检索策略:立即检索(Eager Fetching)、延迟检索(Lazy Fetching)和迫切左外连接检索(Anxious Left Join Fetching)。下面将详细探讨这三种策略的特点。 #### 1. 立即...

    hibernate面试题2

    - Hibernate通过延迟加载策略,只在实际访问数据时才加载,节省内存,提高性能。 7. **类之间的关系映射**: - 通过配置文件如`one-to-many`、`many-to-one`、`many-to-many`等映射关系,实现类与类的关联。 8. ...

    hibernate延迟加载技术详细解

    Fetching 策略定义了 Hibernate 在执行查询时如何获取关联的数据。主要有以下几种: 1. **Join Fetching**:这是一种将主表与关联表通过 OUTER JOIN 连接起来的方式进行查询。这种方式通常用于查询所有相关联数据时...

    hibernate在集合上的lazy策略

    5. **性能优化**:讨论如何根据业务需求调整懒加载策略,以平衡性能和内存使用,可能涉及Eager Fetching、Fetch Graphs和JOIN fetch。 6. **Open Session in View(OSIV)模式**:如果文章涉及,可能会介绍这个模式...

    Hibernate 经典例子全

    在`hibernate_fetch_1`示例中,我们了解到Hibernate的加载策略,包括Eager Fetching(即时加载)和Lazy Fetching(延迟加载)。即时加载会在查询时一起加载关联的对象,而延迟加载则只在真正需要时才执行数据库查询...

    关于hibernate的批处理

    总结,Hibernate的批处理是大数据场景下提高性能的关键技术之一,需要根据具体业务需求和系统资源进行细致的配置和优化。了解并掌握这些知识点,能够帮助开发者更高效地利用Hibernate处理大规模数据。

    hibernate 4.1 core API 英文版

    11. ** Cascading 和 Fetching策略**:Cascading允许开发者设置关联对象的保存、更新、删除行为。Fetching策略则控制何时加载关联对象,包括懒加载(Lazy Loading)和急加载(Eager Loading)。 12. **事件和监听器...

    hibernate源码

    Hibernate提供了多种加载策略,包括立即加载(Eager Fetching)和延迟加载(Lazy Loading)。立即加载会一次性获取所有关联数据,而延迟加载则会在需要时才执行数据库查询。查询缓存则能存储已执行过的查询结果,...

    day36 07-Hibernate抓取策略:many-to-one上的抓取策略

    4. **Subselect Fetching**:这种策略在加载主实体时,同时执行一个子查询来获取关联对象。这种方式适用于关联数据需要复杂条件过滤的情况。 5. **@EntityGraph**:从Hibernate 4.3开始引入,允许我们定义图形化的...

    精通Hibernate:Java对象持久化详解.zip

    6. **Cascading和Fetching策略**:解释如何设置对象间的级联操作,以及优化数据加载的懒加载和立即加载策略。 7. **性能优化**:讨论Hibernate的缓存机制,包括第一级缓存和第二级缓存,以及如何通过配置和设计优化...

    《深入浅出Hibernate》.pdf

    九、Cascading与Fetching策略 Hibernate的级联操作允许在一个对象的操作中自动处理相关对象,如CascadeType.ALL表示所有操作都会影响关联对象。加载策略包括懒加载(Lazy Loading)和急加载(Eager Loading),用于...

    Hibernate 4.1.1 API 文档

    9. **Cascading and Fetching Strategies**:级联操作(Cascading)可以将操作影响范围扩展到关联的对象,而加载策略(Fetching Strategies)则决定了何时以及如何加载关联的数据。 10. **Custom Types**:...

Global site tag (gtag.js) - Google Analytics