Although I always prefer to mark the service method as @Transactional
as a whole, reviewing your code, I think you defined the appropriate transaction demarcation in your methods, by explicitly define the @Transactional
annotation in voidRegistrationToken
, and by using the methods provided by JpaRepository
, implicitly annotated in such a way.
In any case, as you indicated, as a result of performing the different operations over the User
who will be assigned the registration token, you are obtaining inconsistent values.
It is a clear indication that the information of the affected User
entity maintained by the EntityManager
in the persistence context is being polluted somewhere across the different methods invocation.
I honestly cannot give you the exact reason about this behavior.
It may have to do with the moment in which the changes are flushed to the database, to entirely discretion of the EntityManager
, but you already tried to flush the different changes manually and your transactions seems appropriate and, as a consequence, it will probably not be the cause of the problem.
Maybe it have to do with a second level cache as @Guillaume suggested, maybe with the way the @Modifying
operation is implemented by Spring Data.
One think you can try is to instruct your @Modifying
annotation to clear the persistence context once the operation is completed:
@Modifying(clearAutomatically = true)
This will provide you a clean state to perform the registration token update.
Please, see the relevant docs.
Please, be aware that the possible implications of the use of this solution.
The use of flush
and clear
in EntityManager
is an anti-pattern, something that should be avoided if you can by using the appropriate transaction demarcations and component architecture.
The call of clear
leads to all objects being decoupled from the EntityManager
. Be aware that, depending of the use case, even modified object data will not be saved to the database - this is the main difference with flush
that always will preserve the modifications performed to the entities managed in the persistence context before detach them.
In any case, due to the way your transactions are defined, probably in your use case it will work properly.