Using SQLQuery
, Hibernate couldn't know what cache regions you might affect, but luckily you can explicitly instruct it:
SQLQuery sqlQuery = session.createSQLQuery(
"UPDATE CUSTOMER SET ... WHERE ...");
sqlQuery.addSynchronizedEntityClass(Person.class); int
int updateCount = sqlQuery.executeUpdate();
This way it knows what query caches to invalidate, otherwise it may discard everything:
private static class EntityCleanup {
private final EntityRegionAccessStrategy cacheAccess;
private final SoftLock cacheLock;
private EntityCleanup(EntityRegionAccessStrategy cacheAccess) {
this.cacheAccess = cacheAccess;
this.cacheLock = cacheAccess.lockRegion();
cacheAccess.removeAll();
}
private void release() {
cacheAccess.unlockRegion( cacheLock );
}
}
private static class CollectionCleanup {
private final CollectionRegionAccessStrategy cacheAccess;
private final SoftLock cacheLock;
private CollectionCleanup(CollectionRegionAccessStrategy cacheAccess) {
this.cacheAccess = cacheAccess;
this.cacheLock = cacheAccess.lockRegion();
cacheAccess.removeAll();
}
private void release() {
cacheAccess.unlockRegion( cacheLock );
}
}
private class NaturalIdCleanup {
private final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy;
private final SoftLock cacheLock;
public NaturalIdCleanup(NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy) {
this.naturalIdCacheAccessStrategy = naturalIdCacheAccessStrategy;
this.cacheLock = naturalIdCacheAccessStrategy.lockRegion();
naturalIdCacheAccessStrategy.removeAll();
}
private void release() {
naturalIdCacheAccessStrategy.unlockRegion( cacheLock );
}
}
So, as you can see the whole data from the Region
is evicted.
This only affects the second-level cache. The first level cache (a.k.a. Session
) is not cleared every time you run a native query, because that would detach all your current "attached entities", having unexpected consequences in entity state expectations. But before every query (HQL or native) the session is flushed so the DB and the session are in sync prior to executing the query, hence the 1st level cache is consistent before issuing a new select.
A whole region would get invalidated, not the whole second-level cache. An entity defines a cache region, so updating a specific entity table would only remove all the entities that belong to that particular table(s) that were affected by the native query.
But overriding the query-space definition associated with a native query is a way to customize Hibernate not to clear the cache region as it would do using the default implementation.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…