@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) throws CacheException { final EntityPersister persister = getPersister(); if (persister.hasCache()) { final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy(); final Object ck = cache.generateCacheKey( getId(), persister, session.getFactory(), session.getTenantIdentifier()); if (success && cacheEntry != null /*!persister.isCacheInvalidationRequired()*/) { final boolean put = cacheAfterUpdate(cache, ck); if (put && getSession().getFactory().getStatistics().isStatisticsEnabled()) { getSession() .getFactory() .getStatisticsImplementor() .secondLevelCachePut(cache.getRegion().getName()); } } else { cache.unlockItem(session, ck, lock); } } postCommitUpdate(success); }
public void evictEntityRegion(String entityName) { EntityPersister p = getEntityPersister(entityName); if (p.hasCache()) { if (log.isDebugEnabled()) { log.debug("evicting second-level cache: " + p.getEntityName()); } p.getCacheAccessStrategy().evictAll(); } }
public void evictEntity(String entityName, Serializable identifier) { EntityPersister p = getEntityPersister(entityName); if (p.hasCache()) { if (log.isDebugEnabled()) { log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, identifier, SessionFactoryImpl.this)); } p.getCacheAccessStrategy().evict(buildCacheKey(identifier, p)); } }
/** * Closes the session factory, releasing all held resources. * * <ol> * <li>cleans up used cache regions and "stops" the cache provider. * <li>close the JDBC connection * <li>remove the JNDI binding * </ol> * * Note: Be aware that the sessionfactory instance still can be a "heavy" object memory wise after * close() has been called. Thus it is important to not keep referencing the instance to let the * garbage collector release the memory. */ public void close() throws HibernateException { if (isClosed) { log.trace("already closed"); return; } log.info("closing"); isClosed = true; Iterator iter = entityPersisters.values().iterator(); while (iter.hasNext()) { EntityPersister p = (EntityPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } iter = collectionPersisters.values().iterator(); while (iter.hasNext()) { CollectionPersister p = (CollectionPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } if (settings.isQueryCacheEnabled()) { queryCache.destroy(); iter = queryCaches.values().iterator(); while (iter.hasNext()) { QueryCache cache = (QueryCache) iter.next(); cache.destroy(); } updateTimestampsCache.destroy(); } settings.getRegionFactory().stop(); if (settings.isAutoDropSchema()) { schemaExport.drop(false, true); } try { settings.getConnectionProvider().close(); } finally { SessionFactoryObjectFactory.removeInstance(uuid, name, properties); } observer.sessionFactoryClosed(this); eventListeners.destroyListeners(); }
/** * If the class to be loaded has been configured with a cache, then lock given id in that cache * and then perform the load. * * @return The loaded entity * @throws HibernateException */ protected Object lockAndLoad( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final SessionImplementor source) throws HibernateException { CacheConcurrencyStrategy.SoftLock lock = null; final CacheKey ck; if (persister.hasCache()) { ck = new CacheKey( event.getEntityId(), persister.getIdentifierType(), persister.getRootEntityName(), source.getEntityMode(), source.getFactory()); lock = persister.getCache().lock(ck, null); } else { ck = null; } Object entity; try { entity = load(event, persister, keyToLoad, options); } finally { if (persister.hasCache()) { persister.getCache().release(ck, lock); } } Object proxy = event.getSession().getPersistenceContext().proxyFor(persister, keyToLoad, entity); return proxy; }
/** * Attempts to load the entity from the second-level cache. * * @return The entity from the second-level cache, or null. * @throws HibernateException */ protected Object loadFromSecondLevelCache( final LoadEvent event, final EntityPersister persister, final LoadEventListener.LoadType options) throws HibernateException { final SessionImplementor source = event.getSession(); final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled() && event.getLockMode().lessThan(LockMode.READ); if (useCache) { final SessionFactoryImplementor factory = source.getFactory(); final CacheKey ck = new CacheKey( event.getEntityId(), persister.getIdentifierType(), persister.getRootEntityName(), source.getEntityMode(), source.getFactory()); Object ce = persister.getCache().get(ck, source.getTimestamp()); if (factory.getStatistics().isStatisticsEnabled()) { if (ce == null) { factory .getStatisticsImplementor() .secondLevelCacheMiss(persister.getCache().getRegionName()); } else { factory .getStatisticsImplementor() .secondLevelCacheHit(persister.getCache().getRegionName()); } } if (ce != null) { CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure(ce, factory); // Entity was found in second-level cache... return assembleCacheEntry(entry, event.getEntityId(), persister, event); } } return null; }
@Override public void execute() throws HibernateException { final Serializable id = getId(); final EntityPersister persister = getPersister(); final SessionImplementor session = getSession(); final Object instance = getInstance(); final boolean veto = preUpdate(); final SessionFactoryImplementor factory = session.getFactory(); Object previousVersion = this.previousVersion; if (persister.isVersionPropertyGenerated()) { // we need to grab the version value from the entity, otherwise // we have issues with generated-version entities that may have // multiple actions queued during the same flush previousVersion = persister.getVersion(instance); } final Object ck; if (persister.hasCache()) { final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy(); ck = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier()); lock = cache.lockItem(session, ck, previousVersion); } else { ck = null; } if (!veto) { persister.update( id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, rowId, session); } final EntityEntry entry = session.getPersistenceContext().getEntry(instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } if (entry.getStatus() == Status.MANAGED || persister.isVersionPropertyGenerated()) { // get the updated snapshot of the entity state by cloning current state; // it is safe to copy in place, since by this time no-one else (should have) // has a reference to the array TypeHelper.deepCopy( state, persister.getPropertyTypes(), persister.getPropertyCheckability(), state, session); if (persister.hasUpdateGeneratedProperties()) { // this entity defines proeprty generation, so process those generated // values... persister.processUpdateGeneratedProperties(id, instance, state, session); if (persister.isVersionPropertyGenerated()) { nextVersion = Versioning.getVersion(state, persister); } } // have the entity entry doAfterTransactionCompletion post-update processing, passing it the // update state and the new version (if one). entry.postUpdate(instance, state, nextVersion); } if (persister.hasCache()) { if (persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED) { persister.getCacheAccessStrategy().remove(session, ck); } else { // TODO: inefficient if that cache is just going to ignore the updated state! final CacheEntry ce = persister.buildCacheEntry(instance, state, nextVersion, getSession()); cacheEntry = persister.getCacheEntryStructure().structure(ce); final boolean put = cacheUpdate(persister, previousVersion, ck); if (put && factory.getStatistics().isStatisticsEnabled()) { factory .getStatisticsImplementor() .secondLevelCachePut(getPersister().getCacheAccessStrategy().getRegion().getName()); } } } session .getPersistenceContext() .getNaturalIdHelper() .manageSharedNaturalIdCrossReference( persister, id, state, previousNaturalIdValues, CachedNaturalIdValueSource.UPDATE); postUpdate(); if (factory.getStatistics().isStatisticsEnabled() && !veto) { factory.getStatisticsImplementor().updateEntity(getPersister().getEntityName()); } }
private boolean isCachePutEnabled(EntityPersister persister, SessionImplementor session) { return persister.hasCache() && !persister.isCacheInvalidationRequired() && session.getCacheMode().isPutEnabled(); }
public void execute() throws HibernateException { Serializable id = getId(); EntityPersister persister = getPersister(); SessionImplementor session = getSession(); Object instance = getInstance(); boolean veto = preDelete(); Object version = this.version; if (persister.isVersionPropertyGenerated()) { // we need to grab the version value from the entity, otherwise // we have issues with generated-version entities that may have // multiple actions queued during the same flush version = persister.getVersion(instance, session.getEntityMode()); } final CacheKey ck; if (persister.hasCache()) { ck = new CacheKey( id, persister.getIdentifierType(), persister.getRootEntityName(), session.getEntityMode(), session.getFactory()); lock = persister.getCacheAccessStrategy().lockItem(ck, version); } else { ck = null; } if (!isCascadeDeleteEnabled && !veto) { persister.delete(id, version, instance, session); } // postDelete: // After actually deleting a row, record the fact that the instance no longer // exists on the database (needed for identity-column key generation), and // remove it from the session cache final PersistenceContext persistenceContext = session.getPersistenceContext(); EntityEntry entry = persistenceContext.removeEntry(instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } entry.postDelete(); persistenceContext.removeEntity(entry.getEntityKey()); persistenceContext.removeProxy(entry.getEntityKey()); if (persister.hasCache()) { persister.getCacheAccessStrategy().remove(ck); } postDelete(); if (getSession().getFactory().getStatistics().isStatisticsEnabled() && !veto) { getSession() .getFactory() .getStatisticsImplementor() .deleteEntity(getPersister().getEntityName()); } }
/** * Perform the second step of 2-phase load. Fully initialize the entity instance. * * <p>After processing a JDBC result set, we "resolve" all the associations between the entities * which were instantiated and had their state "hydrated" into an array */ public static void initializeEntity( final Object entity, final boolean readOnly, final SessionImplementor session, final PreLoadEvent preLoadEvent, final PostLoadEvent postLoadEvent) throws HibernateException { // TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!) final PersistenceContext persistenceContext = session.getPersistenceContext(); EntityEntry entityEntry = persistenceContext.getEntry(entity); if (entityEntry == null) { throw new AssertionFailure("possible non-threadsafe access to the session"); } EntityPersister persister = entityEntry.getPersister(); Serializable id = entityEntry.getId(); Object[] hydratedState = entityEntry.getLoadedState(); if (log.isDebugEnabled()) log.debug( "resolving associations for " + MessageHelper.infoString(persister, id, session.getFactory())); Type[] types = persister.getPropertyTypes(); for (int i = 0; i < hydratedState.length; i++) { final Object value = hydratedState[i]; if (value != LazyPropertyInitializer.UNFETCHED_PROPERTY && value != BackrefPropertyAccessor.UNKNOWN) { hydratedState[i] = types[i].resolve(value, session, entity); } } // Must occur after resolving identifiers! if (session.isEventSource()) { preLoadEvent.setEntity(entity).setState(hydratedState).setId(id).setPersister(persister); PreLoadEventListener[] listeners = session.getListeners().getPreLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPreLoad(preLoadEvent); } } persister.setPropertyValues(entity, hydratedState, session.getEntityMode()); final SessionFactoryImplementor factory = session.getFactory(); if (persister.hasCache() && session.getCacheMode().isPutEnabled()) { if (log.isDebugEnabled()) log.debug( "adding entity to second-level cache: " + MessageHelper.infoString(persister, id, session.getFactory())); Object version = Versioning.getVersion(hydratedState, persister); CacheEntry entry = new CacheEntry( hydratedState, persister, entityEntry.isLoadedWithLazyPropertiesUnfetched(), version, session, entity); CacheKey cacheKey = new CacheKey( id, persister.getIdentifierType(), persister.getRootEntityName(), session.getEntityMode(), session.getFactory()); boolean put = persister .getCache() .put( cacheKey, persister.getCacheEntryStructure().structure(entry), session.getTimestamp(), version, persister.isVersioned() ? persister.getVersionType().getComparator() : null, useMinimalPuts( session, entityEntry)); // we could use persister.hasLazyProperties() instead of true if (put && factory.getStatistics().isStatisticsEnabled()) { factory .getStatisticsImplementor() .secondLevelCachePut(persister.getCache().getRegionName()); } } if (readOnly || !persister.isMutable()) { // no need to take a snapshot - this is a // performance optimization, but not really // important, except for entities with huge // mutable property values persistenceContext.setEntryStatus(entityEntry, Status.READ_ONLY); } else { // take a snapshot TypeFactory.deepCopy( hydratedState, persister.getPropertyTypes(), persister.getPropertyUpdateability(), hydratedState, // after setting values to object, entityMode session); persistenceContext.setEntryStatus(entityEntry, Status.MANAGED); } persister.afterInitialize(entity, entityEntry.isLoadedWithLazyPropertiesUnfetched(), session); if (session.isEventSource()) { postLoadEvent.setEntity(entity).setId(id).setPersister(persister); PostLoadEventListener[] listeners = session.getListeners().getPostLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPostLoad(postLoadEvent); } } if (log.isDebugEnabled()) log.debug( "done materializing entity " + MessageHelper.infoString(persister, id, session.getFactory())); if (factory.getStatistics().isStatisticsEnabled()) { factory.getStatisticsImplementor().loadEntity(persister.getEntityName()); } }
public boolean containsEntity(String entityName, Serializable identifier) { EntityPersister p = getEntityPersister(entityName); return p.hasCache() && p.getCacheAccessStrategy().getRegion().contains(buildCacheKey(identifier, p)); }
public boolean hasAfterTransactionCompletion() { return persister.hasCache() || hasPostCommitEventListeners(); }