Hibernate – fetching strategies examples
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.
Fetching Strategies
There are four fetching strategies
1. fetch-”join” = Disable the lazy loading, always load all the collections and entities.
2. fetch-”select” (default) = Lazy load all the collections and entities.
3. batch-size=”N” = Fetching up to ‘N’ collections or entities, *Not record*.
4. fetch-”subselect” = Group its collection into a sub select statement.
For detail explanation, you can check on the Hibernate documentation.
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
1. Select statement to retrieve the Stock records -session.get(Stock.class, 114)
2. 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 Stock is initialized. -session.get(Stock.class, 114)
1. Select statement to retrieve the Stock records 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.
1. Select statement to retrieve all the Stock records.
2. Select its related collection
3. Select its related collection
4. Select its related collection
….
21. 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<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()); } }
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.
1. Select statement to retrieve all the Stock records.
2. 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.
Reference
1. http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
2. https://www.hibernate.org/315.html

@ Diyyana Kishore Babu.
Really very good explanation, but one small correction for ?fetch=?select?? strategy.
You mentioned as
?Hibernate generated two select statements
1. Select statement to retrieve the Stock records -session.get(Stock.class, 114)
2. Select its related collections ? sets.iterator()?.
Actually it generate 1(stock) + n(stock_daily_record) for select fetch.
Let?s say stock_daily_record have 10 records it generate 10 select statements and one select statement for stock table.
So Hibernate generate 11 (1+10) select statements for ?select? fetch strategy.
Really very good explanation, but one small correction for ?fetch=?select?? strategy.
You mentioned as
?Hibernate generated two select statements
1. Select statement to retrieve the Stock records -session.get(Stock.class, 114)
2. Select its related collections ? sets.iterator()?.
Actually it generate 1(stock) + n(stock_daily_record) for select fetch.
Let?s say stock_daily_record have 10 records it generate 10 select statements and one select statement for stock table.
So Hibernate generate 11 (1+10) select statements for ‘select’ fetch strategy.
how to define how many records inside in the collections are loaded.
Excellent explanation of fetching strategy with wonderful example !! Thanks.
very nice examples easy to understand……..
Thanks Mkyong for posting very nice article and in a simple way also!!
What is difference between lazy=true and fetch=select as both are responsible to trigger lazy initialization for associated collection.
What is meaning of FetchMode.LAZY and FetchMode.EAGER ..?
I try this example. But I have error
Exception in thread “main” org.hibernate.LazyInitializationException: could not initialize proxy – no Session
Hey Guys there is a possible of doing a OneToMany relationship using criteria and pagination methods(setMaxResult and setFirstResult) and completely LAZY loading the Many relationship[IS Loaded Eagerly on Annotations] thanks a lot.
very nice article.
Thanks for posting this one.
Thanks,
Amit
“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.”
– why are we all dancing around “disaster” again? We all know how JDBC is going to behave. Is it really that hard to read a result set or use a JdbcTemplate or something simple like iBatis? What does hibernate give us that justifies flirting with disaster?
great article, I only have single doubt , how to restrict elements in collections directly on query level ? because the fetchmode=join causes all elements in collection to be fetched and if I apply a Restrictions on associated entities’ properties, It gives me, property not found exception
I have no words to thank you! Just the explanation I was looking for. Great work ..Kudos to you!
Very sharp and crisp explanation…very neat….Thanks…
It was very helpful.
Got exactly what i was looking for. GREAT
Suppose I have an Order table with 50 columns and I have an Order class with 50 properties and mapped with each other in hibernate file. I just want to show order list to the user which may have at most 3 to 4 columns like order_id, date, placed_by and order_amount. My problem starts here… when I load rows through the class, all 50 columns will be loaded along with the required just 4 columns which may impact the performance significantly. And sometime I want to load one (1) order with say 20 columns and sometime want to load a complete order with 50 columns. How can I map these three (3) different scenarios.
Thanks in advance.
Man you rock..Please keep up the good work. We appreciate it a lot!
One word regarding this site is “GREAT”. Very good examples. Please keep it up.
Couldn’t leave this page without saying thanks…
Very nice written article. Concise and easy to following.
Only one question, quote
“…The “join” fetching strategy will disabled the lazy loading of all it’s related collections…”
Let’s say only the following is executed:
I would suspect, the query output should only be:
NOT
select ... from mkyong.stock stock0_ left outer join mkyong.stock_daily_record stockdaily1_ on stock0_.STOCK_ID=stockdaily1_.STOCK_ID where stock0_.STOCK_ID=?Or I missed anything?
Thanks
-Chris
Disable the lazy loading means that Hibernate is going to load the collections or the associations.
Best regards.
Hi Chris,
I agree with you that even after specifing fetch = “Join” I see 2 queries getting fired for the sample you have provided .One for stock and one for stock details. mkyong can you please us know ?
Thanks
Kumaran
Very big fan of you.again very nice article presented by you. Thanks
Thank you @mkyong for placing such a good article with examples.
The article only takes 10-15 minutes to understand the fetching strategies with examples.
If the Batch setting is specified either as annotation on the class or in xml against the table, it is a one time decision. Not sure how practical this feature is.
The application use case should be dictating how many records I want to fetch. Besides I will not know how many records will be returned. So all we are doing is taking a lucky guess as the batch size.
I don’t see myself ever using the feature. I see myself using the Query feature to control how many records are returned.
Great info — this is how information should be presented – present the concept then show the specific details for each concept. Thanks.
Very good article with clear explanation and examples.
very useful..nice to see this kind of article…thanks a lot
your examples are simple but straight to the point.
Easy to understand too.
Very nice article, which not only explains fetching strategies but also n+1 select problem.Thank you.
Its really good site for Hibernate Updates.. Thank you so much..
Short and descriptive, well done. Hoping to see more topics covered.