Search in sources :

Example 16 with EntityEntry

use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.

the class DefaultFlushEntityEventListener method scheduleUpdate.

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 EntityPersister persister = entry.getPersister();
    final Object[] values = event.getPropertyValues();
    if (LOG.isTraceEnabled()) {
        if (status == Status.DELETED) {
            if (!persister.isMutable()) {
                LOG.tracev("Updating immutable, deleted entity: {0}", MessageHelper.infoString(persister, entry.getId(), session.getFactory()));
            } else if (!entry.isModifiableEntity()) {
                LOG.tracev("Updating non-modifiable, deleted entity: {0}", MessageHelper.infoString(persister, entry.getId(), session.getFactory()));
            } else {
                LOG.tracev("Updating deleted entity: ", MessageHelper.infoString(persister, entry.getId(), session.getFactory()));
            }
        } else {
            LOG.tracev("Updating entity: {0}", 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) : entry.getLoadedState()), entry.getVersion(), nextVersion, entity, entry.getRowId(), persister, session));
    return intercepted;
}
Also used : Status(org.hibernate.engine.spi.Status) EntityPersister(org.hibernate.persister.entity.EntityPersister) EntityEntry(org.hibernate.engine.spi.EntityEntry) EventSource(org.hibernate.event.spi.EventSource) AssertionFailure(org.hibernate.AssertionFailure) EntityUpdateAction(org.hibernate.action.internal.EntityUpdateAction) Nullability(org.hibernate.engine.internal.Nullability)

Example 17 with EntityEntry

use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.

the class DefaultFlushEntityEventListener method getNextVersion.

/**
	 * Convenience method to retrieve an entities next version value
	 */
private Object getNextVersion(FlushEntityEvent event) throws HibernateException {
    EntityEntry entry = event.getEntityEntry();
    EntityPersister persister = entry.getPersister();
    if (persister.isVersioned()) {
        Object[] values = event.getPropertyValues();
        if (entry.isBeingReplicated()) {
            return Versioning.getVersion(values, persister);
        } else {
            int[] dirtyProperties = event.getDirtyProperties();
            final boolean isVersionIncrementRequired = isVersionIncrementRequired(event, entry, persister, dirtyProperties);
            final Object nextVersion = isVersionIncrementRequired ? Versioning.increment(entry.getVersion(), persister.getVersionType(), event.getSession()) : //use the current version
            entry.getVersion();
            Versioning.setVersion(values, nextVersion, persister);
            return nextVersion;
        }
    } else {
        return null;
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EntityEntry(org.hibernate.engine.spi.EntityEntry)

Example 18 with EntityEntry

use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.

the class DefaultFlushEntityEventListener method onFlushEntity.

/**
	 * Flushes a single entity's state to the database, by scheduling
	 * an update action, if necessary
	 */
public void onFlushEntity(FlushEntityEvent event) throws HibernateException {
    final Object entity = event.getEntity();
    final EntityEntry entry = event.getEntityEntry();
    final EventSource session = event.getSession();
    final EntityPersister persister = entry.getPersister();
    final Status status = entry.getStatus();
    final Type[] types = persister.getPropertyTypes();
    final boolean mightBeDirty = entry.requiresDirtyCheck(entity);
    final Object[] values = getValues(entity, entry, mightBeDirty, session);
    event.setPropertyValues(values);
    //TODO: avoid this for non-new instances where mightBeDirty==false
    boolean substitute = wrapCollections(session, persister, types, values);
    if (isUpdateNecessary(event, mightBeDirty)) {
        substitute = scheduleUpdate(event) || substitute;
    }
    if (status != Status.DELETED) {
        // now update the object .. has to be outside the main if block above (because of collections)
        if (substitute) {
            persister.setPropertyValues(entity, values);
        }
        // We don't want to touch collections reachable from a deleted object
        if (persister.hasCollections()) {
            new FlushVisitor(session, entity).processEntityPropertyValues(values, types);
        }
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Status(org.hibernate.engine.spi.Status) EntityEntry(org.hibernate.engine.spi.EntityEntry) EventSource(org.hibernate.event.spi.EventSource) Type(org.hibernate.type.Type)

Example 19 with EntityEntry

use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.

the class DefaultFlushEntityEventListener method dirtyCheck.

/**
	 * Perform a dirty check, and attach the results to the event
	 */
protected void dirtyCheck(final 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());
    if (dirtyProperties == null) {
        if (entity instanceof SelfDirtinessTracker) {
            if (((SelfDirtinessTracker) entity).$$_hibernate_hasDirtyAttributes()) {
                dirtyProperties = persister.resolveAttributeIndexes(((SelfDirtinessTracker) entity).$$_hibernate_getDirtyAttributes());
            } else {
                dirtyProperties = new int[0];
            }
        } else {
            // see if the custom dirtiness strategy can tell us...
            class DirtyCheckContextImpl implements CustomEntityDirtinessStrategy.DirtyCheckContext {

                int[] found;

                @Override
                public void doDirtyChecking(CustomEntityDirtinessStrategy.AttributeChecker attributeChecker) {
                    found = new DirtyCheckAttributeInfoImpl(event).visitAttributes(attributeChecker);
                    if (found != null && found.length == 0) {
                        found = null;
                    }
                }
            }
            DirtyCheckContextImpl context = new DirtyCheckContextImpl();
            session.getFactory().getCustomEntityDirtinessStrategy().findDirty(entity, persister, (Session) session, context);
            dirtyProperties = context.found;
        }
    }
    event.setDatabaseSnapshot(null);
    final boolean interceptorHandledDirtyCheck;
    boolean cannotDirtyCheck;
    if (dirtyProperties == null) {
        // Interceptor returned null, so do the dirtycheck ourself, if possible
        try {
            session.getEventListenerManager().dirtyCalculationStart();
            interceptorHandledDirtyCheck = false;
            // object loaded by update()
            cannotDirtyCheck = loadedState == null;
            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()) {
                // 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());
                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);
                }
            }
        } finally {
            session.getEventListenerManager().dirtyCalculationEnd(dirtyProperties != null);
        }
    } else {
        // the Interceptor handled the dirty checking
        cannotDirtyCheck = false;
        interceptorHandledDirtyCheck = true;
    }
    logDirtyProperties(id, dirtyProperties, persister);
    event.setDirtyProperties(dirtyProperties);
    event.setDirtyCheckHandledByInterceptor(interceptorHandledDirtyCheck);
    event.setDirtyCheckPossible(!cannotDirtyCheck);
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker) EntityEntry(org.hibernate.engine.spi.EntityEntry) SessionImplementor(org.hibernate.engine.spi.SessionImplementor)

Example 20 with EntityEntry

use of org.hibernate.engine.spi.EntityEntry in project hibernate-orm by hibernate.

the class DefaultMergeEventListener method existsInDatabase.

private boolean existsInDatabase(Object entity, EventSource source, EntityPersister persister) {
    EntityEntry entry = source.getPersistenceContext().getEntry(entity);
    if (entry == null) {
        Serializable id = persister.getIdentifier(entity, source);
        if (id != null) {
            final EntityKey key = source.generateEntityKey(id, persister);
            final Object managedEntity = source.getPersistenceContext().getEntity(key);
            entry = source.getPersistenceContext().getEntry(managedEntity);
        }
    }
    return entry != null && entry.isExistsInDatabase();
}
Also used : EntityKey(org.hibernate.engine.spi.EntityKey) EntityEntry(org.hibernate.engine.spi.EntityEntry) Serializable(java.io.Serializable)

Aggregations

EntityEntry (org.hibernate.engine.spi.EntityEntry)79 Serializable (java.io.Serializable)22 EntityPersister (org.hibernate.persister.entity.EntityPersister)21 Session (org.hibernate.Session)18 Test (org.junit.Test)17 CollectionEntry (org.hibernate.engine.spi.CollectionEntry)16 AbstractPersistentCollection (org.hibernate.collection.internal.AbstractPersistentCollection)12 EntityKey (org.hibernate.engine.spi.EntityKey)12 TestForIssue (org.hibernate.testing.TestForIssue)12 AssertionFailure (org.hibernate.AssertionFailure)11 HibernateProxy (org.hibernate.proxy.HibernateProxy)11 HibernateException (org.hibernate.HibernateException)10 EventSource (org.hibernate.event.spi.EventSource)9 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)8 TransientObjectException (org.hibernate.TransientObjectException)7 PersistentCollection (org.hibernate.collection.spi.PersistentCollection)7 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)6 Status (org.hibernate.engine.spi.Status)6 LazyInitializer (org.hibernate.proxy.LazyInitializer)6 EntityRegionAccessStrategy (org.hibernate.cache.spi.access.EntityRegionAccessStrategy)5