Search in sources :

Example 6 with Cascade

use of org.hibernate.reactive.engine.impl.Cascade in project hibernate-reactive by hibernate.

the class DefaultReactiveMergeEventListener method fetchAndCopyValues.

private CompletionStage<Void> fetchAndCopyValues(final EntityPersister persister, final Object entity, final Object target, final SessionImplementor source, final MergeContext mergeContext) {
    CompletionStage<Void> stage;
    if (entity == target) {
        // If entity == target, then nothing needs to be fetched.
        stage = voidFuture();
    } else {
        ReactiveSession session = source.unwrap(ReactiveSession.class);
        final Object[] mergeState = persister.getPropertyValues(entity);
        final Object[] managedState = persister.getPropertyValues(target);
        // Cascade-merge mappings do not determine what needs to be fetched.
        // The value only needs to be fetched if the incoming value (mergeState[i])
        // is initialized, but its corresponding managed state is not initialized.
        // Initialization must be done before copyValues() executes.
        stage = loop(0, mergeState.length, i -> Hibernate.isInitialized(mergeState[i]) && !Hibernate.isInitialized(managedState[i]), i -> session.reactiveFetch(managedState[i], true));
    }
    return stage.thenCompose(v -> copyValues(persister, entity, target, source, mergeContext));
}
Also used : CascadingAction(org.hibernate.reactive.engine.impl.CascadingAction) AssertionFailure(org.hibernate.AssertionFailure) EntityPersister(org.hibernate.persister.entity.EntityPersister) EventSource(org.hibernate.event.spi.EventSource) Log(org.hibernate.reactive.logging.impl.Log) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) ForeignKeyDirection(org.hibernate.type.ForeignKeyDirection) MergeEvent(org.hibernate.event.spi.MergeEvent) LoggerFactory(org.hibernate.reactive.logging.impl.LoggerFactory) MergeContext(org.hibernate.event.internal.MergeContext) ObjectDeletedException(org.hibernate.ObjectDeletedException) TO_PARENT(org.hibernate.type.ForeignKeyDirection.TO_PARENT) HibernateProxy(org.hibernate.proxy.HibernateProxy) FROM_PARENT(org.hibernate.type.ForeignKeyDirection.FROM_PARENT) PersistentAttributeInterceptor(org.hibernate.engine.spi.PersistentAttributeInterceptor) Map(java.util.Map) EventUtil(org.hibernate.event.internal.EventUtil) Cascade(org.hibernate.reactive.engine.impl.Cascade) CompletionStages.voidFuture(org.hibernate.reactive.util.impl.CompletionStages.voidFuture) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) ReactiveSession(org.hibernate.reactive.session.ReactiveSession) LazyInitializer(org.hibernate.proxy.LazyInitializer) PersistentAttributeInterceptable(org.hibernate.engine.spi.PersistentAttributeInterceptable) EntityTypes(org.hibernate.reactive.engine.impl.EntityTypes) MethodHandles(java.lang.invoke.MethodHandles) StaleObjectStateException(org.hibernate.StaleObjectStateException) StatisticsImplementor(org.hibernate.stat.spi.StatisticsImplementor) TypeHelper(org.hibernate.type.TypeHelper) EntityKey(org.hibernate.engine.spi.EntityKey) EntityCopyObserver(org.hibernate.event.spi.EntityCopyObserver) ServiceRegistry(org.hibernate.service.ServiceRegistry) Serializable(java.io.Serializable) CompletionStage(java.util.concurrent.CompletionStage) EntityCopyObserverFactory(org.hibernate.event.spi.EntityCopyObserverFactory) ReactiveMergeEventListener(org.hibernate.reactive.event.ReactiveMergeEventListener) MergeEventListener(org.hibernate.event.spi.MergeEventListener) EntityEntry(org.hibernate.engine.spi.EntityEntry) CompletionStages.loop(org.hibernate.reactive.util.impl.CompletionStages.loop) WrongClassException(org.hibernate.WrongClassException) CascadePoint(org.hibernate.engine.internal.CascadePoint) EntityState(org.hibernate.event.internal.EntityState) EnhancementAsProxyLazinessInterceptor(org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) HibernateException(org.hibernate.HibernateException) Hibernate(org.hibernate.Hibernate) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker) DETACHED(org.hibernate.event.internal.EntityState.DETACHED) ReactiveSession(org.hibernate.reactive.session.ReactiveSession)

Example 7 with Cascade

use of org.hibernate.reactive.engine.impl.Cascade in project hibernate-reactive by hibernate.

the class AbstractReactiveSaveEventListener method reactivePerformSaveOrReplicate.

/**
 * Performs all the actual work needed to save an entity (well to get the save moved to
 * the execution queue).
 *
 * @param entity The entity to be saved
 * @param key The id to be used for saving the entity (or null, in the case of identity columns)
 * @param persister The entity's persister instance.
 * @param useIdentityColumn Should an identity column be used for id generation?
 * @param context Generally cascade-specific information.
 * @param source The session which is the source of the current event.
 * @param requiresImmediateIdAccess Is access to the identifier required immediately
 * after the completion of the save?  persist(), for example, does not require this...
 *
 * @return The id used to save the entity; may be null depending on the
 * type of id generator used and the requiresImmediateIdAccess value
 */
protected CompletionStage<Void> reactivePerformSaveOrReplicate(Object entity, EntityKey key, EntityPersister persister, boolean useIdentityColumn, C context, EventSource source, boolean requiresImmediateIdAccess) {
    Serializable id = key == null ? null : key.getIdentifier();
    boolean inTransaction = source.isTransactionInProgress();
    boolean shouldDelayIdentityInserts = !inTransaction && !requiresImmediateIdAccess;
    final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
    // Put a placeholder in entries, so we don't recurse back and try to save() the
    // same object again. QUESTION: should this be done before onSave() is called?
    // likewise, should it be done before onUpdate()?
    EntityEntry original = persistenceContext.addEntry(entity, Status.SAVING, null, null, id, null, LockMode.WRITE, useIdentityColumn, persister, false);
    return cascadeBeforeSave(source, persister, entity, context).thenCompose(v -> {
        // We have to do this after cascadeBeforeSave completes,
        // since it could result in generation of parent ids,
        // which we will need as foreign keys in the insert
        Object[] values = persister.getPropertyValuesToInsert(entity, getMergeMap(context), source);
        Type[] types = persister.getPropertyTypes();
        boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source);
        if (persister.hasCollections()) {
            boolean substituteBecauseOfCollections = visitCollectionsBeforeSave(entity, id, values, types, source);
            substitute = substitute || substituteBecauseOfCollections;
        }
        if (substitute) {
            persister.setPropertyValues(entity, values);
        }
        TypeHelper.deepCopy(values, types, persister.getPropertyUpdateability(), values, source);
        CompletionStage<AbstractEntityInsertAction> insert = addInsertAction(values, id, entity, persister, useIdentityColumn, source, shouldDelayIdentityInserts);
        EntityEntry newEntry = persistenceContext.getEntry(entity);
        if (newEntry != original) {
            EntityEntryExtraState extraState = newEntry.getExtraState(EntityEntryExtraState.class);
            if (extraState == null) {
                newEntry.addExtraState(original.getExtraState(EntityEntryExtraState.class));
            }
        }
        return insert;
    }).thenCompose(vv -> cascadeAfterSave(source, persister, entity, context));
// .thenAccept( v -> {
// postpone initializing id in case the insert has non-nullable transient dependencies
// that are not resolved until cascadeAfterSave() is executed
// Serializable newId = id;
// if ( useIdentityColumn && insert.isEarlyInsert() ) {
// if ( !EntityIdentityInsertAction.class.isInstance( insert ) ) {
// throw new IllegalStateException(
// "Insert should be using an identity column, but action is of unexpected type: " +
// insert.getClass().getName()
// );
// }
// newId = ( (EntityIdentityInsertAction) insert ).getGeneratedId();
// 
// insert.handleNaturalIdPostSaveNotifications( newId );
// }
// return newId;
// } );
}
Also used : CascadingAction(org.hibernate.reactive.engine.impl.CascadingAction) EntityPersister(org.hibernate.persister.entity.EntityPersister) EventSource(org.hibernate.event.spi.EventSource) IdentifierGeneration.assignIdIfNecessary(org.hibernate.reactive.id.impl.IdentifierGeneration.assignIdIfNecessary) AbstractEntityInsertAction(org.hibernate.action.internal.AbstractEntityInsertAction) Log(org.hibernate.reactive.logging.impl.Log) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) LoggerFactory(org.hibernate.reactive.logging.impl.LoggerFactory) Map(java.util.Map) IdentifierGeneration.generateId(org.hibernate.reactive.id.impl.IdentifierGeneration.generateId) NonUniqueObjectException(org.hibernate.NonUniqueObjectException) EntityEntryExtraState(org.hibernate.engine.spi.EntityEntryExtraState) Cascade(org.hibernate.reactive.engine.impl.Cascade) Status(org.hibernate.engine.spi.Status) WrapVisitor(org.hibernate.event.internal.WrapVisitor) ReactiveEntityIdentityInsertAction(org.hibernate.reactive.engine.impl.ReactiveEntityIdentityInsertAction) ReactiveSession(org.hibernate.reactive.session.ReactiveSession) LockMode(org.hibernate.LockMode) Versioning(org.hibernate.engine.internal.Versioning) MethodHandles(java.lang.invoke.MethodHandles) CallbackRegistry(org.hibernate.jpa.event.spi.CallbackRegistry) TypeHelper(org.hibernate.type.TypeHelper) EntityKey(org.hibernate.engine.spi.EntityKey) Serializable(java.io.Serializable) MessageHelper.infoString(org.hibernate.pretty.MessageHelper.infoString) CompletionStages.failedFuture(org.hibernate.reactive.util.impl.CompletionStages.failedFuture) CompletionStage(java.util.concurrent.CompletionStage) CallbackRegistryConsumer(org.hibernate.jpa.event.spi.CallbackRegistryConsumer) EntityEntry(org.hibernate.engine.spi.EntityEntry) CascadePoint(org.hibernate.engine.internal.CascadePoint) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) ReactiveEntityRegularInsertAction(org.hibernate.reactive.engine.impl.ReactiveEntityRegularInsertAction) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker) Type(org.hibernate.type.Type) Serializable(java.io.Serializable) EntityEntry(org.hibernate.engine.spi.EntityEntry) EntityEntryExtraState(org.hibernate.engine.spi.EntityEntryExtraState) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) CompletionStage(java.util.concurrent.CompletionStage)

Aggregations

PersistenceContext (org.hibernate.engine.spi.PersistenceContext)7 EventSource (org.hibernate.event.spi.EventSource)7 Cascade (org.hibernate.reactive.engine.impl.Cascade)7 Serializable (java.io.Serializable)6 MethodHandles (java.lang.invoke.MethodHandles)6 Map (java.util.Map)6 CompletionStage (java.util.concurrent.CompletionStage)6 CascadePoint (org.hibernate.engine.internal.CascadePoint)6 EntityEntry (org.hibernate.engine.spi.EntityEntry)6 EntityKey (org.hibernate.engine.spi.EntityKey)6 EntityPersister (org.hibernate.persister.entity.EntityPersister)6 Log (org.hibernate.reactive.logging.impl.Log)6 LoggerFactory (org.hibernate.reactive.logging.impl.LoggerFactory)6 ReactiveSession (org.hibernate.reactive.session.ReactiveSession)6 HibernateException (org.hibernate.HibernateException)5 SelfDirtinessTracker (org.hibernate.engine.spi.SelfDirtinessTracker)5 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)5 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)5 CascadingAction (org.hibernate.reactive.engine.impl.CascadingAction)5 AssertionFailure (org.hibernate.AssertionFailure)4