Running native mutation query empties out entire L2 cache

When I invoke executeUpdate on a native mutation query (procedure call), Hibernate 6.6.3 clears out almost the entire L2 cache. This is very strange behavior as my cache contains only immutable entities.

It happens at NativeNonSelectQueryPlanImpl#executeUpdate(...) on line 49:

BulkOperationCleanupAction.schedule( session, affectedTableNames );

In my case affectedTableNames is an empty Set.

How can I prevent Hibernate from doing that?

In Hibernate 5.6.15 the implementation made sense. The BulkOperationCleanupAction only considered the initial affected queryable passed to the constructor. This makes sense if you’re updating or deleting an entity.

In Hibernate 6.6.3 the implementation makes no sense as every entity from the entire meta model is considered a candidate (BulkOperationCleanupAction#affectedEntity(...) always returns true in case tableSpaces is empty = procedure call) and if it is cacheable it’s L2 cache is cleared out.

If this is intended then there has to be a way to tell Hibernate to not do that or, even better, tell Hibernate explicitly which entities are going to be affected by the procedure call. Wild-guessing it can be everything is killing the L2 cache performance.

The ProcedureCall interface offers various methods that allow specifying the tables that are affected:

  • addSynchronizedEntityClass
  • addSynchronizedEntityName
  • addSynchronizedQuerySpace

The behavior change was intended. Since Hibernate ORM has no way of knowing what tables are affected when calling a stored procedure, it has to be pessimistic by default and assume every table was changed if you don’t specify that explicitly.

1 Like

The procedure call I use is created using createNativeMutationQuery("{call ContinueProcess(order_type(:id, :orderid, :step, :performer, :next, :addParam))}"). That’s because I have to create an Oracle order_type object for the procedure. So I cannot use createStoredProcedureQuery. Or is there another way?

The NativeQuery interface has the same set of methods, inherited from the SynchronizeableQuery interface.

1 Like

Ok, so a cast to NativeQuery<?> should do the trick. Thank you.