Search in sources :

Example 21 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister 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 22 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultMergeEventListener method onMerge.

/**
	 * Handle the given merge event.
	 *
	 * @param event The merge event to be handled.
	 *
	 * @throws HibernateException
	 */
public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException {
    final MergeContext copyCache = (MergeContext) copiedAlready;
    final EventSource source = event.getSession();
    final Object original = event.getOriginal();
    if (original != null) {
        final Object entity;
        if (original instanceof HibernateProxy) {
            LazyInitializer li = ((HibernateProxy) original).getHibernateLazyInitializer();
            if (li.isUninitialized()) {
                LOG.trace("Ignoring uninitialized proxy");
                event.setResult(source.load(li.getEntityName(), li.getIdentifier()));
                //EARLY EXIT!
                return;
            } else {
                entity = li.getImplementation();
            }
        } else {
            entity = original;
        }
        if (copyCache.containsKey(entity) && (copyCache.isOperatedOn(entity))) {
            LOG.trace("Already in merge process");
            event.setResult(entity);
        } else {
            if (copyCache.containsKey(entity)) {
                LOG.trace("Already in copyCache; setting in merge process");
                copyCache.setOperatedOn(entity, true);
            }
            event.setEntity(entity);
            EntityState entityState = null;
            // Check the persistence context for an entry relating to this
            // entity to be merged...
            EntityEntry entry = source.getPersistenceContext().getEntry(entity);
            if (entry == null) {
                EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
                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);
                    if (entry != null) {
                        // we have specialized case of a detached entity from the
                        // perspective of the merge operation.  Specifically, we
                        // have an incoming entity instance which has a corresponding
                        // entry in the current persistence context, but registered
                        // under a different entity instance
                        entityState = EntityState.DETACHED;
                    }
                }
            }
            if (entityState == null) {
                entityState = getEntityState(entity, event.getEntityName(), entry, source);
            }
            switch(entityState) {
                case DETACHED:
                    entityIsDetached(event, copyCache);
                    break;
                case TRANSIENT:
                    entityIsTransient(event, copyCache);
                    break;
                case PERSISTENT:
                    entityIsPersistent(event, copyCache);
                    break;
                default:
                    //DELETED
                    throw new ObjectDeletedException("deleted instance passed to merge", null, getLoggableName(event.getEntityName(), entity));
            }
        }
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EntityKey(org.hibernate.engine.spi.EntityKey) EventSource(org.hibernate.event.spi.EventSource) LazyInitializer(org.hibernate.proxy.LazyInitializer) EntityEntry(org.hibernate.engine.spi.EntityEntry) Serializable(java.io.Serializable) ObjectDeletedException(org.hibernate.ObjectDeletedException) HibernateProxy(org.hibernate.proxy.HibernateProxy)

Example 23 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultPersistEventListener method entityIsPersistent.

@SuppressWarnings({ "unchecked" })
protected void entityIsPersistent(PersistEvent event, Map createCache) {
    LOG.trace("Ignoring persistent instance");
    final EventSource source = event.getSession();
    //TODO: check that entry.getIdentifier().equals(requestedId)
    final Object entity = source.getPersistenceContext().unproxy(event.getObject());
    final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
    if (createCache.put(entity, entity) == null) {
        justCascade(createCache, source, entity, persister);
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EventSource(org.hibernate.event.spi.EventSource)

Example 24 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultPostLoadEventListener method onPostLoad.

@Override
public void onPostLoad(PostLoadEvent event) {
    final Object entity = event.getEntity();
    final EntityEntry entry = event.getSession().getPersistenceContext().getEntry(entity);
    if (entry == null) {
        throw new AssertionFailure("possible non-threadsafe access to the session");
    }
    final LockMode lockMode = entry.getLockMode();
    if (LockMode.PESSIMISTIC_FORCE_INCREMENT.equals(lockMode)) {
        final EntityPersister persister = entry.getPersister();
        final Object nextVersion = persister.forceVersionIncrement(entry.getId(), entry.getVersion(), event.getSession());
        entry.forceLocked(entity, nextVersion);
    } else if (LockMode.OPTIMISTIC_FORCE_INCREMENT.equals(lockMode)) {
        final EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(entity, entry);
        event.getSession().getActionQueue().registerProcess(incrementVersion);
    } else if (LockMode.OPTIMISTIC.equals(lockMode)) {
        final EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(entity, entry);
        event.getSession().getActionQueue().registerProcess(verifyVersion);
    }
    if (event.getPersister().implementsLifecycle()) {
        //log.debug( "calling onLoad()" );
        ((Lifecycle) event.getEntity()).onLoad(event.getSession(), event.getId());
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EntityEntry(org.hibernate.engine.spi.EntityEntry) AssertionFailure(org.hibernate.AssertionFailure) EntityVerifyVersionProcess(org.hibernate.action.internal.EntityVerifyVersionProcess) Lifecycle(org.hibernate.classic.Lifecycle) LockMode(org.hibernate.LockMode) EntityIncrementVersionProcess(org.hibernate.action.internal.EntityIncrementVersionProcess)

Example 25 with EntityPersister

use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.

the class DefaultRefreshEventListener method onRefresh.

/**
	 * Handle the given refresh event.
	 *
	 * @param event The refresh event to be handled.
	 */
public void onRefresh(RefreshEvent event, Map refreshedAlready) {
    final EventSource source = event.getSession();
    boolean isTransient;
    if (event.getEntityName() != null) {
        isTransient = !source.contains(event.getEntityName(), event.getObject());
    } else {
        isTransient = !source.contains(event.getObject());
    }
    if (source.getPersistenceContext().reassociateIfUninitializedProxy(event.getObject())) {
        if (isTransient) {
            source.setReadOnly(event.getObject(), source.isDefaultReadOnly());
        }
        return;
    }
    final Object object = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
    if (refreshedAlready.containsKey(object)) {
        LOG.trace("Already refreshed");
        return;
    }
    final EntityEntry e = source.getPersistenceContext().getEntry(object);
    final EntityPersister persister;
    final Serializable id;
    if (e == null) {
        persister = source.getEntityPersister(event.getEntityName(), object);
        //refresh() does not pass an entityName
        id = persister.getIdentifier(object, event.getSession());
        if (LOG.isTraceEnabled()) {
            LOG.tracev("Refreshing transient {0}", MessageHelper.infoString(persister, id, source.getFactory()));
        }
        final EntityKey key = source.generateEntityKey(id, persister);
        if (source.getPersistenceContext().getEntry(key) != null) {
            throw new PersistentObjectException("attempted to refresh transient instance when persistent instance was already associated with the Session: " + MessageHelper.infoString(persister, id, source.getFactory()));
        }
    } else {
        if (LOG.isTraceEnabled()) {
            LOG.tracev("Refreshing ", MessageHelper.infoString(e.getPersister(), e.getId(), source.getFactory()));
        }
        if (!e.isExistsInDatabase()) {
            throw new UnresolvableObjectException(e.getId(), "this instance does not yet exist as a row in the database");
        }
        persister = e.getPersister();
        id = e.getId();
    }
    // cascade the refresh prior to refreshing this entity
    refreshedAlready.put(object, object);
    Cascade.cascade(CascadingActions.REFRESH, CascadePoint.BEFORE_REFRESH, source, persister, object, refreshedAlready);
    if (e != null) {
        final EntityKey key = source.generateEntityKey(id, persister);
        source.getPersistenceContext().removeEntity(key);
        if (persister.hasCollections()) {
            new EvictVisitor(source).process(object, persister);
        }
    }
    if (persister.hasCache()) {
        Object previousVersion = null;
        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(object);
        }
        final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
        final Object ck = cache.generateCacheKey(id, persister, source.getFactory(), source.getTenantIdentifier());
        final SoftLock lock = cache.lockItem(source, ck, previousVersion);
        source.getActionQueue().registerProcess(new AfterTransactionCompletionProcess() {

            @Override
            public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
                cache.unlockItem(session, ck, lock);
            }
        });
        cache.remove(source, ck);
    }
    evictCachedCollections(persister, id, source);
    String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
    source.getLoadQueryInfluencers().setInternalFetchProfile("refresh");
    Object result = persister.load(id, object, event.getLockOptions(), source);
    // If it was transient, then set it to the default for the source.
    if (result != null) {
        if (!persister.isMutable()) {
            // this is probably redundant; it should already be read-only
            source.setReadOnly(result, true);
        } else {
            source.setReadOnly(result, (e == null ? source.isDefaultReadOnly() : e.isReadOnly()));
        }
    }
    source.getLoadQueryInfluencers().setInternalFetchProfile(previousFetchProfile);
    UnresolvableObjectException.throwIfNull(result, id, persister.getEntityName());
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) EntityRegionAccessStrategy(org.hibernate.cache.spi.access.EntityRegionAccessStrategy) SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) PersistentObjectException(org.hibernate.PersistentObjectException) EntityKey(org.hibernate.engine.spi.EntityKey) EventSource(org.hibernate.event.spi.EventSource) EntityEntry(org.hibernate.engine.spi.EntityEntry) AfterTransactionCompletionProcess(org.hibernate.action.spi.AfterTransactionCompletionProcess) UnresolvableObjectException(org.hibernate.UnresolvableObjectException) SoftLock(org.hibernate.cache.spi.access.SoftLock)

Aggregations

EntityPersister (org.hibernate.persister.entity.EntityPersister)166 Test (org.junit.Test)59 Serializable (java.io.Serializable)34 Session (org.hibernate.Session)31 Type (org.hibernate.type.Type)29 EntityEntry (org.hibernate.engine.spi.EntityEntry)21 EventSource (org.hibernate.event.spi.EventSource)15 EntityRegionAccessStrategy (org.hibernate.cache.spi.access.EntityRegionAccessStrategy)13 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)13 TestForIssue (org.hibernate.testing.TestForIssue)13 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)12 SequenceStyleGenerator (org.hibernate.id.enhanced.SequenceStyleGenerator)12 EntityType (org.hibernate.type.EntityType)12 ArrayList (java.util.ArrayList)11 CompositeType (org.hibernate.type.CompositeType)11 HibernateProxy (org.hibernate.proxy.HibernateProxy)10 PreparedStatement (java.sql.PreparedStatement)8 List (java.util.List)8 EntityKey (org.hibernate.engine.spi.EntityKey)8 QueryParameters (org.hibernate.engine.spi.QueryParameters)8