Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
DavideD committed Jul 11, 2024
1 parent 228b28c commit bb8bfe6
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,17 @@ public static <T> CompletionStage<Void> cascade(
final EntityPersister persister,
final Object parent,
final T anything) throws HibernateException {
return voidFuture().thenCompose( v -> {
CacheMode cacheMode = eventSource.getCacheMode();
if ( action == CascadingActions.REMOVE ) {
eventSource.setCacheMode( CacheMode.GET );
}
eventSource.getPersistenceContextInternal().incrementCascadeLevel();
return cascadeInternal( action, cascadePoint, eventSource, persister, parent, anything )
.whenComplete( (unused, throwable) -> {
eventSource.getPersistenceContextInternal().decrementCascadeLevel();
eventSource.setCacheMode( cacheMode );
} );
} );
CacheMode cacheMode = eventSource.getCacheMode();
if ( action == CascadingActions.REMOVE ) {
eventSource.setCacheMode( CacheMode.GET );
}
eventSource.getPersistenceContextInternal().incrementCascadeLevel();
return voidFuture()
.thenCompose( v -> cascadeInternal( action, cascadePoint, eventSource, persister, parent, anything ) )
.whenComplete( (unused, throwable) -> {
eventSource.getPersistenceContextInternal().decrementCascadeLevel();
eventSource.setCacheMode( cacheMode );
} );
}

private static <T> CompletionStage<Void> cascadeInternal(
Expand Down Expand Up @@ -270,7 +269,6 @@ private static <T> CompletionStage<Void> cascadeProperty(
final T anything,
final boolean isCascadeDeleteEnabled) throws HibernateException {

CompletionStage<Void> stage = voidFuture();
if ( child != null ) {
if ( type.isAssociationType() ) {
final AssociationType associationType = (AssociationType) type;
Expand All @@ -279,18 +277,8 @@ private static <T> CompletionStage<Void> cascadeProperty(
.isUnownedAssociationTransientCheck();
if ( cascadeAssociationNow( action, cascadePoint, associationType, eventSource.getFactory(), unownedTransient ) ) {
final List<String> path = componentPath;
stage = stage.thenCompose( v -> cascadeAssociation(
action,
cascadePoint,
eventSource,
path,
parent,
child,
type,
style,
anything,
isCascadeDeleteEnabled
) );
return cascadeAssociation( action, cascadePoint, eventSource, path, parent, child, type, style, anything, isCascadeDeleteEnabled )
.thenCompose( v -> cascadeLogicalOneToOne( action, eventSource, path, parent, child, type, style, propertyName, isCascadeDeleteEnabled ) );
}
}
else if ( type.isComponentType() ) {
Expand All @@ -301,40 +289,40 @@ else if ( type.isComponentType() ) {
componentPath.add( propertyName );
}
final List<String> path = componentPath;
stage = stage
.thenCompose( v -> cascadeComponent(
action,
cascadePoint,
eventSource,
path,
parent,
child,
(CompositeType) type,
anything
)
.thenRun( () -> {
if ( path != null ) {
path.remove( path.size() - 1 );
}
} )
);
return cascadeComponent( action, cascadePoint, eventSource, path, parent, child, (CompositeType) type, anything )
.thenRun( () -> {
if ( path != null ) {
path.remove( path.size() - 1 );
}
} )
.thenCompose( v -> cascadeLogicalOneToOne( action, eventSource, path, parent, child, type, style, propertyName, isCascadeDeleteEnabled ) );
}
}
if ( isLogicalOneToOne( type ) ) {
final List<String> path = componentPath;
stage = stage.thenCompose( v -> cascadeLogicalOneToOneOrphanRemoval(
action,
eventSource,
path,
parent,
child,
type,
style,
propertyName,
isCascadeDeleteEnabled
) );
}
return stage;
return cascadeLogicalOneToOne(
action,
eventSource,
componentPath,
parent,
child,
type,
style,
propertyName,
isCascadeDeleteEnabled );
}

private static <T> CompletionStage<Void> cascadeLogicalOneToOne(
CascadingAction<T> action,
EventSource eventSource,
List<String> componentPath,
Object parent,
Object child,
Type type,
CascadeStyle style,
String propertyName,
boolean isCascadeDeleteEnabled) {
return isLogicalOneToOne( type )
? cascadeLogicalOneToOneOrphanRemoval( action, eventSource, componentPath, parent, child, type, style, propertyName, isCascadeDeleteEnabled )
: voidFuture();
}

private static <T> CompletionStage<Void> cascadeLogicalOneToOneOrphanRemoval(
Expand Down Expand Up @@ -611,8 +599,8 @@ private static <T> CompletionStage<Void> cascadeToOne(
if ( style.reallyDoCascade( action.delegate() ) ) {
//not really necessary, but good for consistency...
final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal();
persistenceContext.addChildParent( child, parent );
return voidFuture()
.thenRun( () -> persistenceContext.addChildParent( child, parent ) )
.thenCompose( v -> action.cascade( eventSource, child, entityName, anything, isCascadeDeleteEnabled ) )
.whenComplete( (v, e) -> persistenceContext.removeChildParent( child ) );
}
Expand All @@ -638,9 +626,11 @@ private static <T> CompletionStage<Void> cascadeCollectionElements(
CompletionStage<Void> stage = voidFuture();
if ( reallyDoCascade ) {
final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) {
LOG.tracev( "Cascade {0} for collection: {1}", action, collectionType.getRole() );
}
stage = stage.thenRun( () -> {
if ( traceEnabled ) {
LOG.tracev( "Done cascade {0} for collection: {1}", action, collectionType.getRole() );
}
} );

final Iterator<?> itr = action.getCascadableChildrenIterator( eventSource, collectionType, child );
while ( itr.hasNext() ) {
Expand All @@ -665,6 +655,17 @@ private static <T> CompletionStage<Void> cascadeCollectionElements(
} );
}

return stage
.thenCompose( v -> doDeleteOrphans( action, eventSource, child, collectionType, style, elemType ) );
}

private static <T> CompletionStage<Void> doDeleteOrphans(
CascadingAction<T> action,
EventSource eventSource,
Object child,
CollectionType collectionType,
CascadeStyle style,
Type elemType) {
final boolean deleteOrphans = style.hasOrphanDelete()
&& action.deleteOrphans()
&& elemType.isEntityType()
Expand All @@ -673,30 +674,28 @@ private static <T> CompletionStage<Void> cascadeCollectionElements(
&& ! ( (PersistentCollection<?>) child ).isNewlyInstantiated();

if ( deleteOrphans ) {
stage = stage.thenCompose( v -> {
final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) {
LOG.tracev( "Deleting orphans for collection: {0}", collectionType.getRole() );
}
// we can do the cast since orphan-delete does not apply to:
// 1. newly instantiated collections
// 2. arrays (we can't track orphans for detached arrays)
final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() );
return deleteOrphans( eventSource, entityName, (PersistentCollection<?>) child )
.thenRun( () -> {
if ( traceEnabled ) {
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
}
} );
} );
final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) {
LOG.tracev( "Deleting orphans for collection: {0}", collectionType.getRole() );
}
// we can do the cast since orphan-delete does not apply to:
// 1. newly instantiated collections
// 2. arrays (we can't track orphans for detached arrays)
final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() );
return doDeleteOrphans( eventSource, entityName, (PersistentCollection<?>) child )
.thenRun( () -> {
if ( traceEnabled ) {
LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() );
}
} );
}
return stage;
return voidFuture();
}

/**
* Delete any entities that were removed from the collection
*/
private static CompletionStage<Void> deleteOrphans(EventSource eventSource, String entityName, PersistentCollection<?> pc) {
private static CompletionStage<Void> doDeleteOrphans(EventSource eventSource, String entityName, PersistentCollection<?> pc) {
final Collection<?> orphans = getOrphans( eventSource, entityName, pc );
final ReactiveSession session = (ReactiveSession) eventSource;
return loop( orphans, Objects::nonNull, orphan -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import io.vertx.core.net.impl.pool.CombinerExecutor;
import io.vertx.core.net.impl.pool.Executor;
import io.vertx.core.net.impl.pool.Task;

import org.hibernate.reactive.id.ReactiveIdentifierGenerator;
import org.hibernate.reactive.session.ReactiveConnectionSupplier;
import org.hibernate.reactive.util.impl.CompletionStages;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
Expand All @@ -29,7 +29,6 @@
* @author Gavin King
* @author Davide D'Alto
* @author Sanne Grinovero
*
*/
public abstract class BlockingIdentifierGenerator implements ReactiveIdentifierGenerator<Long> {

Expand Down Expand Up @@ -83,40 +82,41 @@ public CompletionStage<Long> generate(ReactiveConnectionSupplier connectionSuppl
//(this does actually hit a synchronization, but it's extremely short)
final long next = next();
if ( next != -1 ) {
return CompletionStages.completedFuture( next );
return completedFuture( next );
}

//Another special case we need to deal with; this is an unlikely configuration, but
//if it were to happen we should be better off with direct execution rather than using
//the co-operative executor:
if ( getBlockSize() <= 1 ) {
return nextHiValue( connectionSupplier )
.thenApply( i -> next( i ) );
return nextHiValue( connectionSupplier ).thenApply( this::next );
}

final CompletableFuture<Long> resultForThisEventLoop = new CompletableFuture<>();
final CompletableFuture<Long> result = new CompletableFuture<>();
executor.submit( new GenerateIdAction( connectionSupplier, result ) );
final Context context = Vertx.currentContext();
result.whenComplete( (id,t) -> {
executor.submit( new GenerateIdAction( connectionSupplier, result ) );
result.whenComplete( (id, t) -> {
final Context newContext = Vertx.currentContext();
//Need to be careful in resuming processing on the same context as the original
//request, potentially having to switch back if we're no longer executing on the same:
if ( newContext != context ) {
if ( t != null ) {
context.runOnContext( ( v ) -> resultForThisEventLoop.completeExceptionally( t ) );
} else {
context.runOnContext( ( v ) -> resultForThisEventLoop.complete( id ) );
context.runOnContext( v -> resultForThisEventLoop.completeExceptionally( t ) );
}
else {
context.runOnContext( v -> resultForThisEventLoop.complete( id ) );
}
}
else {
if ( t != null ) {
resultForThisEventLoop.completeExceptionally( t );
} else {
}
else {
resultForThisEventLoop.complete( id );
}
}
});
} );
return resultForThisEventLoop;
}

Expand All @@ -126,8 +126,8 @@ private final class GenerateIdAction implements Executor.Action<GeneratorState>
private final CompletableFuture<Long> result;

public GenerateIdAction(ReactiveConnectionSupplier connectionSupplier, CompletableFuture<Long> result) {
this.connectionSupplier = Objects.requireNonNull(connectionSupplier);
this.result = Objects.requireNonNull(result);
this.connectionSupplier = Objects.requireNonNull( connectionSupplier );
this.result = Objects.requireNonNull( result );
}

@Override
Expand All @@ -137,21 +137,22 @@ public Task execute(GeneratorState state) {
// We don't need to update or initialize the hi
// value in the table, so just increment the lo
// value and return the next id in the block
completedFuture( local )
.whenComplete( this::acceptAsReturnValue );
completedFuture( local ).whenComplete( this::acceptAsReturnValue );
return null;
} else {
}
else {
nextHiValue( connectionSupplier )
.whenComplete( (newlyGeneratedHi, throwable) -> {
if ( throwable != null ) {
result.completeExceptionally( throwable );
} else {
}
else {
//We ignore the state argument as we actually use the field directly
//for convenience, but they are the same object.
executor.submit( stateIgnored -> {
result.complete( next( newlyGeneratedHi ) );
return null;
});
} );
}
} );
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import java.util.Objects;
import java.util.concurrent.CompletionStage;

import static java.util.function.Function.identity;

/**
* @author Gavin King
*/
Expand Down Expand Up @@ -46,7 +48,7 @@ public void initialize(SqlStringGenerationContext context) {

@Override
public CompletionStage<Object> generate(ReactiveConnectionSupplier session, Object entity) {
return reactiveGenerator.generate( session, entity ).thenApply( id -> id );
return reactiveGenerator.generate( session, entity ).thenApply( identity() );
}

@Override
Expand Down
3 changes: 0 additions & 3 deletions hibernate-reactive-core/src/test/resources/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ logger.sql-connection.level = info
logger.reactive-engine.name = org.hibernate.reactive.engine.impl
logger.reactive-engine.level = trace

logger.orm-engine.name = org.hibernate.engine
logger.orm-engine.level = trace

# Setting level to TRACE will show parameters values
logger.sql-parameters-values.name = org.hibernate.type
logger.sql-parameters-values.level = info
Expand Down

0 comments on commit bb8bfe6

Please sign in to comment.