@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);
  }
 @Override
 public void evictAll() throws CacheException {
   try {
     actualStrategy.evictAll();
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
   }
 }
 @Override
 public void unlockRegion(SoftLock lock) throws CacheException {
   try {
     actualStrategy.unlockRegion(lock);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
   }
 }
 @Override
 public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
   try {
     actualStrategy.remove(session, key);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
   }
 }
 @Override
 public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock)
     throws CacheException {
   try {
     actualStrategy.unlockItem(session, key, lock);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
   }
 }
 @Override
 public SoftLock lockRegion() throws CacheException {
   try {
     return actualStrategy.lockRegion();
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return null;
   }
 }
 private boolean cacheAfterUpdate(EntityRegionAccessStrategy cache, Object ck) {
   final SessionImplementor session = getSession();
   SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
   try {
     eventListenerManager.cachePutStart();
     return cache.afterUpdate(session, ck, cacheEntry, nextVersion, previousVersion, lock);
   } finally {
     eventListenerManager.cachePutEnd();
   }
 }
 @Override
 public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp)
     throws CacheException {
   try {
     return actualStrategy.get(session, key, txTimestamp);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return null;
   }
 }
 @Override
 public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version)
     throws CacheException {
   try {
     return actualStrategy.lockItem(session, key, version);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return null;
   }
 }
 @Override
 public boolean afterInsert(
     SharedSessionContractImplementor session, Object key, Object value, Object version)
     throws CacheException {
   try {
     return actualStrategy.afterInsert(session, key, value, version);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return false;
   }
 }
 @Override
 public boolean update(
     SharedSessionContractImplementor session,
     Object key,
     Object value,
     Object currentVersion,
     Object previousVersion)
     throws CacheException {
   try {
     return actualStrategy.update(session, key, value, currentVersion, previousVersion);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return false;
   }
 }
 @Override
 public boolean putFromLoad(
     SharedSessionContractImplementor session,
     Object key,
     Object value,
     long txTimestamp,
     Object version)
     throws CacheException {
   try {
     return actualStrategy.putFromLoad(session, key, value, txTimestamp, version);
   } catch (NonStopCacheException nonStopCacheException) {
     hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException);
     return false;
   }
 }
  @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());
    }
  }
 @Override
 public EntityRegion getRegion() {
   return actualStrategy.getRegion();
 }