use of org.hibernate.cache.spi.access.CollectionDataAccess in project hibernate-orm by hibernate.
the class CollectionLoadContext method addCollectionToCache.
/**
* Add the collection to the second-level cache
*
* @param lce The entry representing the collection to add
* @param persister The persister
*/
private void addCollectionToCache(LoadingCollectionEntry lce, CollectionPersister persister) {
final SharedSessionContractImplementor session = getLoadContext().getPersistenceContext().getSession();
final SessionFactoryImplementor factory = session.getFactory();
final boolean debugEnabled = LOG.isDebugEnabled();
if (debugEnabled) {
LOG.debugf("Caching collection: %s", MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session));
}
if (!session.getLoadQueryInfluencers().getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters(session)) {
// some filters affecting the collection are enabled on the session, so do not do the put into the cache.
if (debugEnabled) {
LOG.debug("Refusing to add to cache due to enabled filters");
}
// EARLY EXIT!!!!!
return;
}
final Object version;
if (persister.isVersioned()) {
Object collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner(lce.getKey(), persister);
if (collectionOwner == null) {
// resolution against the PC anyway just to be safe since the lookup should not be costly.
if (lce.getCollection() != null) {
final Object linkedOwner = lce.getCollection().getOwner();
if (linkedOwner != null) {
final Serializable ownerKey = persister.getOwnerEntityPersister().getIdentifier(linkedOwner, session);
collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner(ownerKey, persister);
}
}
if (collectionOwner == null) {
throw new HibernateException("Unable to resolve owner of loading collection [" + MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session) + "] for second level caching");
}
}
version = getLoadContext().getPersistenceContext().getEntry(collectionOwner).getVersion();
} else {
version = null;
}
final CollectionCacheEntry entry = new CollectionCacheEntry(lce.getCollection(), persister);
final CollectionDataAccess cacheAccess = persister.getCacheAccessStrategy();
final Object cacheKey = cacheAccess.generateCacheKey(lce.getKey(), persister, session.getFactory(), session.getTenantIdentifier());
boolean isPutFromLoad = true;
if (persister.getElementType().isAssociationType()) {
for (Serializable id : entry.getState()) {
EntityPersister entityPersister = ((QueryableCollection) persister).getElementPersister();
if (session.getPersistenceContext().wasInsertedDuringTransaction(entityPersister, id)) {
isPutFromLoad = false;
break;
}
}
}
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
if (isPutFromLoad) {
try {
session.getEventListenerManager().cachePutStart();
final boolean put = cacheAccess.putFromLoad(session, cacheKey, persister.getCacheEntryStructure().structure(entry), version, factory.getSessionFactoryOptions().isMinimalPutsEnabled() && session.getCacheMode() != CacheMode.REFRESH);
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().collectionCachePut(persister.getNavigableRole(), persister.getCacheAccessStrategy().getRegion().getName());
}
} finally {
session.getEventListenerManager().cachePutEnd();
}
}
}
use of org.hibernate.cache.spi.access.CollectionDataAccess in project hibernate-orm by hibernate.
the class DynamicFilterTest method testSecondLevelCachedCollectionsFiltering.
@Test
public void testSecondLevelCachedCollectionsFiltering() {
TestData testData = new TestData();
testData.prepare();
Session session = openSession();
long ts = ((SessionImplementor) session).getTimestamp();
// Force a collection into the second level cache, with its non-filtered elements
Salesperson sp = (Salesperson) session.load(Salesperson.class, testData.steveId);
Hibernate.initialize(sp.getOrders());
CollectionPersister persister = sessionFactory().getCollectionPersister(Salesperson.class.getName() + ".orders");
assertTrue("No cache for collection", persister.hasCache());
CollectionDataAccess cache = persister.getCacheAccessStrategy();
Object cacheKey = cache.generateCacheKey(testData.steveId, persister, sessionFactory(), session.getTenantIdentifier());
CollectionCacheEntry cachedData = (CollectionCacheEntry) cache.get((SessionImplementor) session, cacheKey);
assertNotNull("collection was not in cache", cachedData);
session.close();
session = openSession();
ts = ((SessionImplementor) session).getTimestamp();
session.enableFilter("fulfilledOrders").setParameter("asOfDate", testData.lastMonth.getTime());
sp = (Salesperson) session.createQuery("from Salesperson as s where s.id = :id").setLong("id", testData.steveId).uniqueResult();
assertEquals("Filtered-collection not bypassing 2L-cache", 1, sp.getOrders().size());
Object cacheKey2 = cache.generateCacheKey(testData.steveId, persister, sessionFactory(), session.getTenantIdentifier());
CollectionCacheEntry cachedData2 = (CollectionCacheEntry) persister.getCacheAccessStrategy().get((SessionImplementor) session, cacheKey2);
assertNotNull("collection no longer in cache!", cachedData2);
assertSame("Different cache values!", cachedData, cachedData2);
session.close();
session = openSession();
session.enableFilter("fulfilledOrders").setParameter("asOfDate", testData.lastMonth.getTime());
sp = (Salesperson) session.load(Salesperson.class, testData.steveId);
assertEquals("Filtered-collection not bypassing 2L-cache", 1, sp.getOrders().size());
session.close();
// Finally, make sure that the original cached version did not get over-written
session = openSession();
sp = (Salesperson) session.load(Salesperson.class, testData.steveId);
assertEquals("Actual cached version got over-written", 2, sp.getOrders().size());
session.close();
testData.release();
}
use of org.hibernate.cache.spi.access.CollectionDataAccess in project hibernate-orm by hibernate.
the class DefaultRefreshEventListener method evictCachedCollections.
private void evictCachedCollections(Type[] types, Serializable id, EventSource source) throws HibernateException {
for (Type type : types) {
if (type.isCollectionType()) {
CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister(((CollectionType) type).getRole());
if (collectionPersister.hasCache()) {
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(id, collectionPersister, source.getFactory(), source.getTenantIdentifier());
final SoftLock lock = cache.lockItem(source, ck, null);
cache.remove(source, ck);
source.getActionQueue().registerProcess((success, session) -> cache.unlockItem(session, ck, lock));
}
} else if (type.isComponentType()) {
CompositeType actype = (CompositeType) type;
evictCachedCollections(actype.getSubtypes(), id, source);
}
}
}
use of org.hibernate.cache.spi.access.CollectionDataAccess in project hibernate-orm by hibernate.
the class CollectionAction method beforeExecutions.
@Override
public final void beforeExecutions() throws CacheException {
// the database (this action is responsible for second-level cache invalidation only)
if (persister.hasCache()) {
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(key, persister, session.getFactory(), session.getTenantIdentifier());
final SoftLock lock = cache.lockItem(session, ck, null);
// the old behavior used key as opposed to getKey()
afterTransactionProcess = new CacheCleanupProcess(key, persister, lock);
}
}
use of org.hibernate.cache.spi.access.CollectionDataAccess in project hibernate-orm by hibernate.
the class EnabledCaching method evictCollectionData.
@Override
public void evictCollectionData(String role, Serializable ownerIdentifier) {
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel().collectionPersister(role);
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
if (cacheAccess == null) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debugf("Evicting second-level cache: %s", MessageHelper.collectionInfoString(collectionDescriptor, ownerIdentifier, sessionFactory));
}
final Object key = cacheAccess.generateCacheKey(ownerIdentifier, collectionDescriptor, sessionFactory, null);
cacheAccess.evict(key);
}
Aggregations