I have had a hunt around for an answer to this but have not found one, so apologies if it has been answered before.
I need to process a large result set. Mostly this is fine, but I have a OneToMany relationship within the main entity: public class Stock { ... @OneToMany(fetch = FetchType.LAZY) @JoinColumn(referencedColumnName = "p_uuid", name = "uuid") @Where(clause = "alias_type_id IN (1,2,4)") @BatchSize(size = 10) private Collection<Alias> aliases; ... }
If I load 100 results like this because I am using custom SQL:
session.createSQLQuery(sql).addEntity(Stock.class).list();
And iterate through the results, then as expected I only see 10 queries for the aliases collection rather than 100 because each of them is initialising 10 collections rather than just one.
However, I don't just have 100 rows, I have about 7 million so I can't just use list() in the general case because I will run out of RAM while loading all the results. So I use a scrollable result set like this:
session.createSQLQuery(sql).addEntity(Stock.class).scroll(ScrollMode.FORWARD_ONLY);
Now when I iterate through those results, I can iterate through as many as I like, but each of them will issue its own query to populate the aliases collection and appears to ignore the @BatchSize annotation.
My thoughts on the reason is: In the list() case, all results are loaded at once and while this is happening, Hibernate gets the opportunity to initialise the collections in batches. But in the scroll() case, Hibernate is loading and initialising one result at a time and therefore does not get the opportunity to batch anything together.
Is there any way to get collection batching working in conjunction with scrollable results? Or is there another approach that would satisfy my need to process a large resultset and keeping the collection batching?
Thanks!
|