Search in sources :

Example 6 with CollectionDataAccess

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();
        }
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) CollectionCacheEntry(org.hibernate.cache.spi.entry.CollectionCacheEntry) HibernateException(org.hibernate.HibernateException) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) CollectionDataAccess(org.hibernate.cache.spi.access.CollectionDataAccess)

Example 7 with CollectionDataAccess

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();
}
Also used : CollectionCacheEntry(org.hibernate.cache.spi.entry.CollectionCacheEntry) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) CollectionDataAccess(org.hibernate.cache.spi.access.CollectionDataAccess) Session(org.hibernate.Session) Test(org.junit.Test)

Example 8 with CollectionDataAccess

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);
        }
    }
}
Also used : CollectionType(org.hibernate.type.CollectionType) CompositeType(org.hibernate.type.CompositeType) Type(org.hibernate.type.Type) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) CollectionDataAccess(org.hibernate.cache.spi.access.CollectionDataAccess) SoftLock(org.hibernate.cache.spi.access.SoftLock) CompositeType(org.hibernate.type.CompositeType)

Example 9 with CollectionDataAccess

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);
    }
}
Also used : CollectionDataAccess(org.hibernate.cache.spi.access.CollectionDataAccess) SoftLock(org.hibernate.cache.spi.access.SoftLock)

Example 10 with CollectionDataAccess

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);
}
Also used : CollectionPersister(org.hibernate.persister.collection.CollectionPersister) CollectionDataAccess(org.hibernate.cache.spi.access.CollectionDataAccess)

Aggregations

CollectionDataAccess (org.hibernate.cache.spi.access.CollectionDataAccess)13 CollectionPersister (org.hibernate.persister.collection.CollectionPersister)7 HibernateException (org.hibernate.HibernateException)3 Session (org.hibernate.Session)3 CollectionCacheEntry (org.hibernate.cache.spi.entry.CollectionCacheEntry)3 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)3 EntityDataAccess (org.hibernate.cache.spi.access.EntityDataAccess)2 NaturalIdDataAccess (org.hibernate.cache.spi.access.NaturalIdDataAccess)2 SoftLock (org.hibernate.cache.spi.access.SoftLock)2 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)2 EntityPersister (org.hibernate.persister.entity.EntityPersister)2 Type (org.hibernate.type.Type)2 Test (org.junit.Test)2 Serializable (java.io.Serializable)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 EmbeddableType (javax.persistence.metamodel.EmbeddableType)1