When doing heavy read-only operations in with the database it can be a good idea to take advantage of using Hibernate's Stateless Session
As it name indicates this session does not keep state of the entities that it retrieves from the database and so it bypasses the L1 and L2 cache
This can have significant performance impact on heavy DBA read operations (since the state of the entities is not bet tracked)
@Component @Scope("prototype") public class SomeJpaService { public static final int SCROLL_STEP = 1000; @PersistenceContext private EntityManager entityManager; public void doInStatelessSession(){ LOGGER.info("ABOUT to perform Heavy read operation on DB"); StatelessSession statelessSession = entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession(); try (ScrollableResults r = statelessSession .createQuery("SELECT c FROM Order c") .setReadOnly(true) .setCacheable(false) .scroll()) {// create the scrollable results with a try/close resources block while (r.scroll(SCROLL_STEP)) { Order o = (Order) r.get(0); //perform some operation on object } } LOGGER.info("FINISHED heavy read operation"); statelessSession.close(); } }
There's however a few caveats with this approach :
- Collections cannot be fetched on stateless sessions
- Because of the stateless nature of the session this can only be used on read-only operations
"Because of the stateless nature of the session this can only be used on read-only operations"
ReplyDeleteIt could be used on write operations, however it does not handle cascading (see StatelessSession#insert), dirty checks and so on (StatelessSession javaDoc says more on it)