Search in sources :

Example 1 with EntityState

use of org.hibernate.event.internal.EntityState in project hibernate-reactive by hibernate.

the class DefaultReactiveMergeEventListener method reactiveOnMerge.

/**
 * Handle the given merge event.
 *
 * @param event The merge event to be handled.
 */
@Override
public CompletionStage<Void> reactiveOnMerge(MergeEvent event, MergeContext copyCache) throws HibernateException {
    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 voidFuture();
            } else {
                entity = li.getImplementation();
            }
        } else if (original instanceof PersistentAttributeInterceptable) {
            final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) original;
            final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
            if (interceptor instanceof EnhancementAsProxyLazinessInterceptor) {
                final EnhancementAsProxyLazinessInterceptor proxyInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
                LOG.trace("Ignoring uninitialized enhanced-proxy");
                // no need to go async, AFAICT ?
                event.setResult(source.load(proxyInterceptor.getEntityName(), (Serializable) proxyInterceptor.getIdentifier()));
                // EARLY EXIT!
                return voidFuture();
            } else {
                entity = original;
            }
        } 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...
            final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
            EntityEntry entry = persistenceContext.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 = persistenceContext.getEntity(key);
                    entry = persistenceContext.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 = DETACHED;
                    }
                }
            }
            if (entityState == null) {
                entityState = EntityState.getEntityState(entity, event.getEntityName(), entry, source, false);
            }
            switch(entityState) {
                case DETACHED:
                    return entityIsDetached(event, copyCache);
                case TRANSIENT:
                    return entityIsTransient(event, copyCache);
                case PERSISTENT:
                    return entityIsPersistent(event, copyCache);
                default:
                    // DELETED
                    throw new ObjectDeletedException("deleted instance passed to merge", null, EventUtil.getLoggableName(event.getEntityName(), entity));
            }
        }
    }
    return voidFuture();
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) LazyInitializer(org.hibernate.proxy.LazyInitializer) Serializable(java.io.Serializable) PersistentAttributeInterceptor(org.hibernate.engine.spi.PersistentAttributeInterceptor) PersistentAttributeInterceptable(org.hibernate.engine.spi.PersistentAttributeInterceptable) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) EntityState(org.hibernate.event.internal.EntityState) HibernateProxy(org.hibernate.proxy.HibernateProxy) EnhancementAsProxyLazinessInterceptor(org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor) EntityKey(org.hibernate.engine.spi.EntityKey) EventSource(org.hibernate.event.spi.EventSource) EntityEntry(org.hibernate.engine.spi.EntityEntry) ObjectDeletedException(org.hibernate.ObjectDeletedException)

Example 2 with EntityState

use of org.hibernate.event.internal.EntityState in project hibernate-reactive by hibernate.

the class DefaultReactivePersistEventListener method reactiveOnPersist.

/**
 * Handle the given create event.
 *
 * @param event The create event to be handled.
 */
public CompletionStage<Void> reactiveOnPersist(PersistEvent event, IdentitySet createCache) throws HibernateException {
    final SessionImplementor source = event.getSession();
    final Object object = event.getObject();
    final Object entity;
    if (object instanceof HibernateProxy) {
        LazyInitializer li = ((HibernateProxy) object).getHibernateLazyInitializer();
        if (li.isUninitialized()) {
            if (li.getSession() == source) {
                // NOTE EARLY EXIT!
                return voidFuture();
            } else {
                return failedFuture(new PersistentObjectException("uninitialized proxy passed to persist()"));
            }
        }
        entity = li.getImplementation();
    } else {
        entity = object;
    }
    final String entityName;
    if (event.getEntityName() != null) {
        entityName = event.getEntityName();
    } else {
        entityName = source.bestGuessEntityName(entity);
        event.setEntityName(entityName);
    }
    final EntityEntry entityEntry = source.getPersistenceContextInternal().getEntry(entity);
    EntityState entityState = EntityState.getEntityState(entity, entityName, entityEntry, source, true);
    if (entityState == EntityState.DETACHED) {
        // JPA 2, in its version of a "foreign generated", allows the id attribute value
        // to be manually set by the user, even though this manual value is irrelevant.
        // The issue is that this causes problems with the Hibernate unsaved-value strategy
        // which comes into play here in determining detached/transient state.
        // 
        // Detect if we have this situation and if so null out the id value and calculate the
        // entity state again.
        // NOTE: entityEntry must be null to get here, so we cannot use any of its values
        EntityPersister persister = source.getFactory().getMetamodel().entityPersister(entityName);
        if (persister.getIdentifierGenerator() instanceof ForeignGenerator) {
            if (LOG.isDebugEnabled() && persister.getIdentifier(entity, source) != null) {
                LOG.debug("Resetting entity id attribute to null for foreign generator");
            }
            persister.setIdentifier(entity, null, source);
            entityState = EntityState.getEntityState(entity, entityName, entityEntry, source, true);
        }
    }
    switch(entityState) {
        case DETACHED:
            {
                return failedFuture(new PersistentObjectException("detached entity passed to persist: " + EventUtil.getLoggableName(event.getEntityName(), entity)));
            }
        case PERSISTENT:
            {
                return entityIsPersistent(event, createCache);
            }
        case TRANSIENT:
            {
                return entityIsTransient(event, createCache);
            }
        case DELETED:
            {
                entityEntry.setStatus(Status.MANAGED);
                entityEntry.setDeletedState(null);
                event.getSession().getActionQueue().unScheduleDeletion(entityEntry, event.getObject());
                return entityIsDeleted(event, createCache);
            }
        default:
            {
                return failedFuture(new ObjectDeletedException("deleted entity passed to persist", null, EventUtil.getLoggableName(event.getEntityName(), entity)));
            }
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) LazyInitializer(org.hibernate.proxy.LazyInitializer) EntityEntry(org.hibernate.engine.spi.EntityEntry) ForeignGenerator(org.hibernate.id.ForeignGenerator) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) ObjectDeletedException(org.hibernate.ObjectDeletedException) MessageHelper.infoString(org.hibernate.pretty.MessageHelper.infoString) EntityState(org.hibernate.event.internal.EntityState) PersistentObjectException(org.hibernate.PersistentObjectException) HibernateProxy(org.hibernate.proxy.HibernateProxy)

Aggregations

ObjectDeletedException (org.hibernate.ObjectDeletedException)2 EntityEntry (org.hibernate.engine.spi.EntityEntry)2 EntityState (org.hibernate.event.internal.EntityState)2 EntityPersister (org.hibernate.persister.entity.EntityPersister)2 HibernateProxy (org.hibernate.proxy.HibernateProxy)2 LazyInitializer (org.hibernate.proxy.LazyInitializer)2 Serializable (java.io.Serializable)1 PersistentObjectException (org.hibernate.PersistentObjectException)1 EnhancementAsProxyLazinessInterceptor (org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor)1 EntityKey (org.hibernate.engine.spi.EntityKey)1 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)1 PersistentAttributeInterceptable (org.hibernate.engine.spi.PersistentAttributeInterceptable)1 PersistentAttributeInterceptor (org.hibernate.engine.spi.PersistentAttributeInterceptor)1 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)1 EventSource (org.hibernate.event.spi.EventSource)1 ForeignGenerator (org.hibernate.id.ForeignGenerator)1 MessageHelper.infoString (org.hibernate.pretty.MessageHelper.infoString)1