0

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.

tm1701
  • 7,307
  • 17
  • 79
  • 168
  • I would suggest you remove the `@Transactional` annotation, if you want to use flush and clear there. That annotation tells Spring (and subsequently Hibernate and the database) that it MUST keep everything in memory until the commit, which in your case is a lot of data. – coladict Jul 21 '21 at 14:00
  • Thank you for your reaction! Can I read so much data from the data without any@Transactional? – tm1701 Jul 21 '21 at 15:43

1 Answers1

1

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.

Christian Beikov
  • 15,141
  • 2
  • 32
  • 58