Search code examples
springhibernatejpahibernate-jpa

Spring JPA: keeping the persistence context small


How can I keep the persistence context small in a Spring JPA environment?

Why: I know that by keeping the persistence context small, there will be a significant performance boost!

The main problem area is:

@Transactional
void MethodA() { 
   WHILE retrieving next object of 51M (via a stateless session connection) DO
      get some further (readonly) data
      IF condition holds THEN
        assessment = retrieve assession object (= record from database)
        change assessment data
        save the assessment to the database
}

Via experiments in this problem domain I know that when cleaning the persistence context every 250 iterations, then the performance will be a lot better.

When I add these lines to the code, so every 250 iterations:

@PersistenceContext
private EntityManager em;

WHILE ... 
   ...
   IF counter++ % 250 == 0 THEN
       em.flush()
       em.clear() 
}

Then I get errors like "cannot reliably perform the flush operation".

I tried to make the main Transactional read-only and the asssessment-save part 'Transaction-requires-new', then I get errors like 'operating on a detached entity'. Very strange, because I never revisit an open entity.

So, how can I keep the persistence context small? Have tried 10s of ways. Help is really appreciated.


Solution

  • I would suggest you move all the condition logic into your query so that you don't even have to load that many rows/objects. Or even better, write an update query that does all of that in a single transaction so you don't need to transfer any data at all between your application and database.

    I don't think that flushing is necessary with a stateless session as it doesn't keep state i.e. it flushes and clears the persistence context after every operation, but apart from that, I also think this this might not be what you really want as that could lead to re-fetching of data.

    If you don't want the persistence context to fill up, then use DTOs for fetching the data and execute update statements to flush the changes.