Home > Software design >  How to get updated objects after flush() in the same transaction (Hibernate/ Spring boot)
How to get updated objects after flush() in the same transaction (Hibernate/ Spring boot)

Time:01-12

I have a list of ~10 000 objects.

I am trying to call an mysql update query (procedure) and then to get the updated objects inside same transaction. Can this be achieved ?

When I call a delete statement flush(), hibernate retrieves me correct objects (deleted objects are missing) But when I try update statement flush(), hibernate retrieves me the initial unchanged objects.

@Transactional
void test() {
  //...
  em.createQuery("delete from StorefrontProduct sp where sp in (:storefrontProducts)")
                    .setParameter("storefrontProducts", storefrontProductsToDelete)
                    .executeUpdate();

  // example
  em.createQuery("update StorefrontProduct sp set sp.orderIndex=0 where sp.id=90")
                            .executeUpdate();
  em.flush();

  //Simple JPA query
  List<StorefrontProduct> result = repository.findAllByPreviousOrderIndexIsNotNull();

  //additional code....
}

After running the code from above and putting a breakpoint after findAll call, provided objects from 1-st query were deleted and flushed, but the update query was not flushed.

CodePudding user response:

That is known counterintuitive behaviour of Hibernate.

First of all, em.flush() call might be superfluous if flush mode set to AUTO (in that case Hibernate automatically synchronises persistence context (session-level cache) with underlying database prior executing update/delete queries).

Delete and successive Select case:

  • you issues delete then select, since select does not see deleted records anymore you do not see deleted records in resultset, however if you call findById you may find deleted records.

Update and successive Select case:

  • you issues update then select, when processing resultset Hibernate sees both records stored in database and records stored in persistence context and it assumes that persistence context is a source of truth, that is the reason why you see "stale" data.

There are following options to mitigate that counterintuitive behaviour:

  1. do not perform direct updates, use "slow" find/save API instead
  2. either detach or refresh stale entities after direct update, em.clear() may also help, however it completely cleans up persistence context, which might be undesirable
  • Related