Hibernate – fetching strategies examples
2015-09-18 13:54
357 查看
Hibernate has few fetching strategies to optimize the Hibernate generated select statement, so that it can be as efficient as possible. The fetching strategy is declared in the mapping relationship to define how Hibernate fetch its related collections and entities.
fetch-“join” = Disable the lazy loading, always load all the collections and entities.
fetch-“select” (default) = Lazy load all the collections and entities.
batch-size=”N” = Fetching up to ‘N’ collections or entities, Not record.
fetch-“subselect” = Group its collection into a sub select statement.
Example to declare fetch strategies in XML file
Example to declare fetch strategies in annotation
Let explore how fetch strategies affect the Hibernate generated SQL statement.
1.
This is the default fetching strategy. it enabled the lazy loading of all it’s related collections. Let see the example…
Output
Hibernate generated two select statements
Select statement to retrieve the
Select its related collections –
2.
The “
Output
Hibernate generated only one select statement, it retrieve all its related collections when the
Select statement to retrieve the
3.
This ‘batch size’ fetching strategy is always misunderstanding by many Hibernate developers. Let see the misunderstand concept here…
What is your expected result, is this per-fetch 10 records from collection? See the output
The batch-size did nothing here, it is not how batch-size work. See this statement.
The batch-size fetching strategy is not define how many records inside in the collections are loaded. Instead, it defines how many collections should be loaded.
— Repeat N times until you remember this statement —
No batch-size fetching strategy
Keep repeat the select statements….depend how many stock records in your table.
If you have 20 stock records in the database, the Hibernate’s default fetching strategies will generate 20+1 select statements and hit the database.
Select statement to retrieve all the Stock records.
Select its related collection
Select its related collection
Select its related collection
….
Select its related collection
The generated queries are not efficient and caused a serious performance issue.
Enabled the
Let see another example with
List list = session.createQuery(“from Stock”).list();
for(Stock stock : list){
}
Hibernate:
select …
from mkyong.stock stock0_
Hibernate:
select …
from
mkyong.stock_daily_record stockdaily0_
where
stockdaily0_.STOCK_ID in (
select
stock0_.STOCK_ID
from
mkyong.stock stock0_
)
Select statement to retrieve all the Stock records.
Select all its related collections in a sub select query.
Fetching Strategies
There are four fetching strategiesfetch-“join” = Disable the lazy loading, always load all the collections and entities.
fetch-“select” (default) = Lazy load all the collections and entities.
batch-size=”N” = Fetching up to ‘N’ collections or entities, Not record.
fetch-“subselect” = Group its collection into a sub select statement.
Fetching strategies examples
Here’s a “one-to-many relationship” example for the fetching strategies demonstration. A stock is belong to many stock daily records.Example to declare fetch strategies in XML file
... <hibernate-mapping> <class name="com.mkyong.common.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.mkyong.common.StockDailyRecord" /> </set> </class> </hibernate-mapping>
Example to declare fetch strategies in annotation
... @Entity @Table(name = "stock", catalog = "mkyong") 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; } ... }
Let explore how fetch strategies affect the Hibernate generated SQL statement.
1. fetch=”select”
or @Fetch(FetchMode.SELECT)
This is the default fetching strategy. it enabled the lazy loading of all it’s related collections. Let see the example…//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()); }
Output
Hibernate: select ...from mkyong.stock where stock0_.STOCK_ID=? Hibernate: select ...from mkyong.stock_daily_record where stockdaily0_.STOCK_ID=?
Hibernate generated two select statements
Select statement to retrieve the
Stockrecords –
session.get(Stock.class, 114)
Select its related collections –
sets.iterator()
2. fetch=”join”
or @Fetch(FetchMode.JOIN)
The “join” fetching strategy will disabled the lazy loading of all it’s related collections. Let see the example…
//call select from stock and stock_daily_record Stock stock = (Stock)session.get(Stock.class, 114); Set sets = stock.getStockDailyRecords(); //no extra select for ( Iterator iter = sets.iterator();iter.hasNext(); ) { StockDailyRecord sdr = (StockDailyRecord) iter.next(); System.out.println(sdr.getDailyRecordId()); System.out.println(sdr.getDate()); }
Output
Hibernate: select ... from mkyong.stock stock0_ left outer join mkyong.stock_daily_record stockdaily1_ on stock0_.STOCK_ID=stockdaily1_.STOCK_ID where stock0_.STOCK_ID=?
Hibernate generated only one select statement, it retrieve all its related collections when the
Stockis initialized. –
session.get(Stock.class, 114)
Select statement to retrieve the
Stockrecords and outer join its related collections.
3. batch-size=”10″
or @BatchSize(size = 10)
This ‘batch size’ fetching strategy is always misunderstanding by many Hibernate developers. Let see the misunderstand concept here…Stock stock = (Stock)session.get(Stock.class, 114); 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()); }
What is your expected result, is this per-fetch 10 records from collection? See the output
Output
Hibernate: select ...from mkyong.stock where stock0_.STOCK_ID=? Hibernate: select ...from mkyong.stock_daily_record where stockdaily0_.STOCK_ID=?
The batch-size did nothing here, it is not how batch-size work. See this statement.
The batch-size fetching strategy is not define how many records inside in the collections are loaded. Instead, it defines how many collections should be loaded.
— Repeat N times until you remember this statement —
Another example
Let see another example, you want to print out all the stock records and its related stock daily records (collections) one by one.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()); } }
No batch-size fetching strategy
Output
Hibernate: select ... from mkyong.stock stock0_ Hibernate: select ... from mkyong.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID=? Hibernate: select ... from mkyong.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID=?
Keep repeat the select statements….depend how many stock records in your table.
If you have 20 stock records in the database, the Hibernate’s default fetching strategies will generate 20+1 select statements and hit the database.
Select statement to retrieve all the Stock records.
Select its related collection
Select its related collection
Select its related collection
….
Select its related collection
The generated queries are not efficient and caused a serious performance issue.
Enabled the
batch-size=’10’fetching strategy
Let see another example with
batch-size=’10’ is enabled.
Output
Hibernate: select ... from mkyong.stock stock0_ Hibernate: select ... from mkyong.stock_daily_record stockdaily0_ where stockdaily0_.STOCK_ID in ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ``` Now, Hibernate will per-fetch the collections, with a select *in* statement. If you have 20 stock records, it will generate 3 select statements. 1. Select statement to retrieve all the Stock records. 2. Select In statement to per-fetch its related collections (10 collections a time) 3. Select In statement to per-fetch its related collections (next 10 collections a time) With `batch-size` enabled, it simplify the select statements from 21 select statements to 3 select statements. ##4. `fetch=”subselect`” or `@Fetch(FetchMode.SUBSELECT)` This fetching strategy is enable all its related collection in a sub select statement. Let see the same query again..
List 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()); }
}
###Output
Hibernate:
select …
from mkyong.stock stock0_
Hibernate:
select …
from
mkyong.stock_daily_record stockdaily0_
where
stockdaily0_.STOCK_ID in (
select
stock0_.STOCK_ID
from
mkyong.stock stock0_
)
`` With “subselect`” enabled, it will create two select statements.
Select statement to retrieve all the Stock records.
Select all its related collections in a sub select query.
Conclusion
The fetching strategies are highly flexible and a very important tweak to optimize the Hibernate query, but if you used it in a wrong place, it will be a total disaster.相关文章推荐
- Hibernate Oracle sequence的使用技巧
- jsp Hibernate批量更新和批量删除处理代码
- jsp hibernate的分页代码第1/3页
- JAVA+Hibernate 无限级分类
- SSH整合中 hibernate托管给Spring得到SessionFactory
- jsp hibernate 数据保存操作的原理
- hibernate中的增删改查实现代码
- 解决hibernate+mysql写入数据库乱码
- java优化hibernate性能的几点建议
- java Hibernate延迟加载
- hibernate 常用方法介绍
- 深入理解Hibernate中的flush机制
- 简单的手工hibernate程序示例
- 解析使用jdbc,hibernate处理clob/blob字段的详解
- 浅析java程序中hibernate的应用总结
- java面试常见问题之Hibernate总结
- 关于Hibernate的一些学习心得总结
- Hibernate管理Session和批量操作分析
- 基于spring+hibernate+JQuery开发之电子相册(附源码下载)
- java Hibernate 一对多自身关联问题