protected boolean handleInterception(FlushEntityEvent event) {
    SessionImplementor session = event.getSession();
    EntityEntry entry = event.getEntityEntry();
    EntityPersister persister = entry.getPersister();
    Object entity = event.getEntity();

    // give the Interceptor a chance to modify property values
    final Object[] values = event.getPropertyValues();
    final boolean intercepted = invokeInterceptor(session, entity, entry, values, persister);

    // now we might need to recalculate the dirtyProperties array
    if (intercepted && event.isDirtyCheckPossible() && !event.isDirtyCheckHandledByInterceptor()) {
      int[] dirtyProperties;
      if (event.hasDatabaseSnapshot()) {
        dirtyProperties =
            persister.findModified(event.getDatabaseSnapshot(), values, entity, session);
      } else {
        dirtyProperties = persister.findDirty(values, entry.getLoadedState(), entity, session);
      }
      event.setDirtyProperties(dirtyProperties);
    }

    return intercepted;
  }
  /** Perform a dirty check, and attach the results to the event */
  protected void dirtyCheck(FlushEntityEvent event) throws HibernateException {

    final Object entity = event.getEntity();
    final Object[] values = event.getPropertyValues();
    final SessionImplementor session = event.getSession();
    final EntityEntry entry = event.getEntityEntry();
    final EntityPersister persister = entry.getPersister();
    final Serializable id = entry.getId();
    final Object[] loadedState = entry.getLoadedState();

    int[] dirtyProperties =
        session
            .getInterceptor()
            .findDirty(
                entity,
                id,
                values,
                loadedState,
                persister.getPropertyNames(),
                persister.getPropertyTypes());

    event.setDatabaseSnapshot(null);

    final boolean interceptorHandledDirtyCheck;
    boolean cannotDirtyCheck;

    if (dirtyProperties == null) {
      // Interceptor returned null, so do the dirtycheck ourself, if possible
      interceptorHandledDirtyCheck = false;

      cannotDirtyCheck = loadedState == null; // object loaded by update()
      if (!cannotDirtyCheck) {
        // dirty check against the usual snapshot of the entity
        dirtyProperties = persister.findDirty(values, loadedState, entity, session);
      } else if (entry.getStatus() == Status.DELETED
          && !event.getEntityEntry().isModifiableEntity()) {
        // A non-modifiable (e.g., read-only or immutable) entity needs to be have
        // references to transient entities set to null before being deleted. No other
        // fields should be updated.
        if (values != entry.getDeletedState()) {
          throw new IllegalStateException(
              "Entity has status Status.DELETED but values != entry.getDeletedState");
        }
        // Even if loadedState == null, we can dirty-check by comparing currentState and
        // entry.getDeletedState() because the only fields to be updated are those that
        // refer to transient entities that are being set to null.
        // - currentState contains the entity's current property values.
        // - entry.getDeletedState() contains the entity's current property values with
        //   references to transient entities set to null.
        // - dirtyProperties will only contain properties that refer to transient entities
        final Object[] currentState =
            persister.getPropertyValues(event.getEntity(), event.getSession().getEntityMode());
        dirtyProperties =
            persister.findDirty(entry.getDeletedState(), currentState, entity, session);
        cannotDirtyCheck = false;
      } else {
        // dirty check against the database snapshot, if possible/necessary
        final Object[] databaseSnapshot = getDatabaseSnapshot(session, persister, id);
        if (databaseSnapshot != null) {
          dirtyProperties = persister.findModified(databaseSnapshot, values, entity, session);
          cannotDirtyCheck = false;
          event.setDatabaseSnapshot(databaseSnapshot);
        }
      }
    } else {
      // the Interceptor handled the dirty checking
      cannotDirtyCheck = false;
      interceptorHandledDirtyCheck = true;
    }

    logDirtyProperties(id, dirtyProperties, persister);

    event.setDirtyProperties(dirtyProperties);
    event.setDirtyCheckHandledByInterceptor(interceptorHandledDirtyCheck);
    event.setDirtyCheckPossible(!cannotDirtyCheck);
  }