Issue
Consider a typical task, when we have to build huge file report, by scrolling appropriate results from DB. ORM framework is Hibernate
.
We know, that there are 3 ways, how to avoid OutOfMemoryException
for such pattern:
-
ScrollableResults customers = session.createQuery("from Customers order by id").scroll(ScrollMode.FORWARD_ONLY); while (customers.next()) { Customer customer = (Customer) customers.get(0); addDataToReport(customer); session.evict(customer); }
Use
session.clear()
:ScrollableResults customers = session.createQuery("from Customers order by id").scroll(ScrollMode.FORWARD_ONLY); int i = 0; while (customers.next()) { Customer customer = (Customer) customers.get(0); addDataToReport(customer); if ( ++i % 1000 == 0) session.clear(); }
Use
CacheMode.IGNORE
:ScrollableResults customers = session.createQuery("from Customers order by id").setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); while (customers.next()) { Customer customer = (Customer) customers.get(0); addDataToReport(customer); }
So, the question is: which of these methods is most better (in sense of performance) for mentioned purposes? Or may be there are more effective other methods?
Solution
CacheMode.IGNORE
has nothing to do with your problem. It's about 2nd level cache, not session cache.evict()
doesn't evict related entities if relationship is configured withoutCascadeType.DETACH
orCascadeType.ALL
. It means that:- Related entities without cascaded eviction will accumulate in memory
- Related entities with cascaded eviction will be reloaded on each iteration, even if the are the same
- Threfore approach with
clear()
is the best option:- When invoked, it evicts all entities from the session cache
- It's not invoked on each iteration, so that you can leverage session cache for related entities
Answered By - axtavt
Answer Checked By - Mary Flores (JavaFixing Volunteer)