JPA Saveandflush() Doesn'T Reflect Immediately In Database

Related topic:

Problem

When doing kafka events to communicate between two different microservices (Spring Batch). We experienced a problem that:

  • Microservice A saved the record before sending out the event in a Spring Batch step
  • Microservice B received the event
  • Microservice B query for the same record and sometimes cannot find the record.

Issue

So as the two note above saying, saveAndFlush() even though it flushes into the database, it only visible after the program exits the transaction. The flush() in here is for visibility within the same transaction. Other service can see or cannot see depends on the isolation level that we set.

Since we're sending event from Spring Batch. By default the transaction is happening at chunk level, therefore even with saveAndFlush(), the other application won't receive the update until the chunk finished processing

Solution

We decided to mark saveAndFlush() as @Transactional(propagation = Propagation.REQUIRES_NEW) to override the default propagation of REQUIRED (which merge into the existing one for saving resources) that will create a new transaction instead of merging with the current one to guarantee that other application can see it.

interface SomeRepository extends CrudRepository {
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	saveAndFLush();
}

This is because after executing saveAndFlush(), the transaction will finished and it will be COMMITED_READ which other application can see.