/** * Performs all necessary checking to determine if an entity needs an SQL update to synchronize * its state to the database. Modifies the event by side-effect! Note: this method is quite slow, * avoid calling if possible! */ protected final boolean isUpdateNecessary(FlushEntityEvent event) throws HibernateException { EntityPersister persister = event.getEntityEntry().getPersister(); Status status = event.getEntityEntry().getStatus(); if (!event.isDirtyCheckPossible()) { return true; } else { int[] dirtyProperties = event.getDirtyProperties(); if (dirtyProperties != null && dirtyProperties.length != 0) { return true; // TODO: suck into event class } else { return hasDirtyCollections(event, persister, status); } } }
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; }
private boolean scheduleUpdate(final FlushEntityEvent event) { final EntityEntry entry = event.getEntityEntry(); final EventSource session = event.getSession(); final Object entity = event.getEntity(); final Status status = entry.getStatus(); final EntityMode entityMode = session.getEntityMode(); final EntityPersister persister = entry.getPersister(); final Object[] values = event.getPropertyValues(); if (LOG.isTraceEnabled()) { if (status == Status.DELETED) { if (!persister.isMutable()) LOG.trace( "Updating immutable, deleted entity: " + MessageHelper.infoString(persister, entry.getId(), session.getFactory())); else if (!entry.isModifiableEntity()) LOG.trace( "Updating non-modifiable, deleted entity: " + MessageHelper.infoString(persister, entry.getId(), session.getFactory())); else LOG.trace( "Updating deleted entity: " + MessageHelper.infoString(persister, entry.getId(), session.getFactory())); } else LOG.trace( "Updating entity: " + MessageHelper.infoString(persister, entry.getId(), session.getFactory())); } final boolean intercepted = !entry.isBeingReplicated() && handleInterception(event); // increment the version number (if necessary) final Object nextVersion = getNextVersion(event); // if it was dirtied by a collection only int[] dirtyProperties = event.getDirtyProperties(); if (event.isDirtyCheckPossible() && dirtyProperties == null) { if (!intercepted && !event.hasDirtyCollection()) { throw new AssertionFailure("dirty, but no dirty properties"); } dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY; } // check nullability but do not doAfterTransactionCompletion command execute // we'll use scheduled updates for that. new Nullability(session).checkNullability(values, persister, true); // schedule the update // note that we intentionally do _not_ pass in currentPersistentState! session .getActionQueue() .addAction( new EntityUpdateAction( entry.getId(), values, dirtyProperties, event.hasDirtyCollection(), (status == Status.DELETED && !entry.isModifiableEntity() ? persister.getPropertyValues(entity, entityMode) : entry.getLoadedState()), entry.getVersion(), nextVersion, entity, entry.getRowId(), persister, session)); return intercepted; }