First of all, I want to clarify that I'm talking about short lived Session, i.e. one Session per HTTP request in a servlet container.
In this scenario I think that it would make sense get a local Query Cache per session by default whit the possibility of disable it explicitly for specific queries (like we do for enable Query Cache with Criteria#setCacheable).
Well, the improvement of performance is obvious in cases where you execute the same query in different components of your application, e.g first in an advice to do some validations and after in a service that performs the business logic.
Besides that why we should execute the same query again if the Session Cache will end up asking to the StatefulPersistentContext if the objects are already hidrated and discarding the rows if they are?
There are a couple of situations when may be reasonably execute the query again:
1. You are doing a projection and you want it includes changes commited by other transactions.
2. You are doing a projection and you want it includes changes commited by the current transaction.
3. You are querying a list of entities and you want it includes entities created by other transactions.
4. You are querying a list of entities and you want it includes entities created by the current transaction.
Cases 2 & 4 could be done keeping track of what spaces have changed within the current transaction. This logic is already present in the UpdateTimestampsCache only that in this case it shouldn't be shared between transactions or replicated across servers. It's also present if we use FlushMode.AUTO.
Cases 1 & 3 should be explicitly treated via something like Criteria#skipLocalQueryCache.
It's true that we could achieve this local query cache using query.setCacheable(true).setCacheRegion(<localQueryCacheRegionID>); where localQueryCacheRegionID should be generated per request.
However this region would be invalidated by modifications of another sessions.
I'm not the first to think in a query cache on a session level only