Skip to content

Commit 78179b1

Browse files
blafondDavideD
authored andcommitted
[hibernate#1077] Added support for non-nullable associations
1 parent 7bdc2f0 commit 78179b1

File tree

3 files changed

+111
-19
lines changed

3 files changed

+111
-19
lines changed

hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/ReactiveActionQueue.java

+19-19
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
3535
import org.hibernate.action.spi.Executable;
3636
import org.hibernate.cache.CacheException;
37-
import org.hibernate.engine.internal.NonNullableTransientDependencies;
3837
import org.hibernate.engine.spi.ActionQueue;
3938
import org.hibernate.engine.spi.EntityEntry;
4039
import org.hibernate.engine.spi.ExecutableList;
@@ -343,24 +342,25 @@ private CompletionStage<Void> addInsertAction(ReactiveEntityInsertAction insert)
343342
ret = ret.thenCompose( v -> executeInserts() );
344343
}
345344

346-
NonNullableTransientDependencies nonNullableTransientDependencies = insert.findNonNullableTransientEntities();
347-
if ( nonNullableTransientDependencies == null ) {
348-
LOG.tracev( "Adding insert with no non-nullable, transient entities: [{0}]", insert );
349-
ret = ret.thenCompose( v -> addResolvedEntityInsertAction( insert ) );
350-
}
351-
else {
352-
if ( LOG.isTraceEnabled() ) {
353-
LOG.tracev( "Adding insert with non-nullable, transient entities; insert=[{0}], dependencies=[{1}]",
354-
insert,
355-
nonNullableTransientDependencies.toLoggableString( insert.getSession() )
356-
);
357-
}
358-
if ( unresolvedInsertions == null ) {
359-
unresolvedInsertions = new UnresolvedEntityInsertActions();
360-
}
361-
unresolvedInsertions.addUnresolvedEntityInsertAction( (AbstractEntityInsertAction) insert, nonNullableTransientDependencies );
362-
}
363-
return ret;
345+
return ret
346+
.thenCompose( v -> insert.reactiveFindNonNullableTransientEntities() )
347+
.thenCompose( nonNullables -> {
348+
if ( nonNullables == null ) {
349+
LOG.tracev( "Adding insert with no non-nullable, transient entities: [{0}]", insert );
350+
return addResolvedEntityInsertAction( insert );
351+
}
352+
else {
353+
if ( LOG.isTraceEnabled() ) {
354+
LOG.tracev( "Adding insert with non-nullable, transient entities; insert=[{0}], dependencies=[{1}]", insert, nonNullables.toLoggableString( insert.getSession() ) );
355+
}
356+
if ( unresolvedInsertions == null ) {
357+
unresolvedInsertions = new UnresolvedEntityInsertActions();
358+
}
359+
unresolvedInsertions
360+
.addUnresolvedEntityInsertAction( (AbstractEntityInsertAction) insert, nonNullables );
361+
return voidFuture();
362+
}
363+
} );
364364
}
365365

366366
private CompletionStage<Void> addResolvedEntityInsertAction(ReactiveEntityInsertAction insert) {

hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ForeignKeys.java

+88
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import org.hibernate.HibernateException;
1010
import org.hibernate.TransientObjectException;
1111
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
12+
import org.hibernate.engine.internal.NonNullableTransientDependencies;
1213
import org.hibernate.engine.spi.EntityEntry;
1314
import org.hibernate.engine.spi.SelfDirtinessTracker;
1415
import org.hibernate.engine.spi.SessionImplementor;
16+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1517
import org.hibernate.internal.util.StringHelper;
1618
import org.hibernate.persister.entity.EntityPersister;
1719
import org.hibernate.proxy.HibernateProxy;
@@ -359,6 +361,92 @@ public static CompletionStage<Object> getEntityIdentifierIfNotUnsaved(
359361
}
360362
}
361363

364+
public static CompletionStage<NonNullableTransientDependencies> findNonNullableTransientEntities(
365+
String entityName,
366+
Object entity,
367+
Object[] values,
368+
boolean isEarlyInsert,
369+
SharedSessionContractImplementor session) {
370+
371+
final EntityPersister persister = session.getEntityPersister( entityName, entity );
372+
final Type[] types = persister.getPropertyTypes();
373+
final Nullifier nullifier = new Nullifier( entity, false, isEarlyInsert, (SessionImplementor) session, persister );
374+
final String[] propertyNames = persister.getPropertyNames();
375+
final boolean[] nullability = persister.getPropertyNullability();
376+
final NonNullableTransientDependencies nonNullableTransientEntities = new NonNullableTransientDependencies();
377+
378+
return loop( 0, types.length,
379+
i -> collectNonNullableTransientEntities(
380+
nullifier,
381+
values[i],
382+
propertyNames[i],
383+
types[i],
384+
nullability[i],
385+
session,
386+
nonNullableTransientEntities
387+
)
388+
).thenApply( r -> nonNullableTransientEntities.isEmpty() ? null : nonNullableTransientEntities );
389+
}
390+
391+
private static CompletionStage<Void> collectNonNullableTransientEntities(
392+
Nullifier nullifier,
393+
Object value,
394+
String propertyName,
395+
Type type,
396+
boolean isNullable,
397+
SharedSessionContractImplementor session,
398+
NonNullableTransientDependencies nonNullableTransientEntities) {
399+
400+
if ( value == null ) {
401+
return voidFuture();
402+
}
403+
404+
if ( type.isEntityType() ) {
405+
final EntityType entityType = (EntityType) type;
406+
if ( !isNullable && !entityType.isOneToOne() ) {
407+
return nullifier
408+
.isNullifiable( entityType.getAssociatedEntityName(), value )
409+
.thenAccept( isNullifiable -> {
410+
if ( isNullifiable ) {
411+
nonNullableTransientEntities.add( propertyName, value );
412+
}
413+
} );
414+
}
415+
}
416+
else if ( type.isAnyType() ) {
417+
if ( !isNullable ) {
418+
return nullifier
419+
.isNullifiable( null, value )
420+
.thenAccept( isNullifiable -> {
421+
if ( isNullifiable ) {
422+
nonNullableTransientEntities.add( propertyName, value );
423+
}
424+
} );
425+
};
426+
}
427+
else if ( type.isComponentType() ) {
428+
final CompositeType actype = (CompositeType) type;
429+
final boolean[] subValueNullability = actype.getPropertyNullability();
430+
if ( subValueNullability != null ) {
431+
final String[] subPropertyNames = actype.getPropertyNames();
432+
final Object[] subvalues = actype.getPropertyValues( value, session );
433+
final Type[] subtypes = actype.getSubtypes();
434+
return loop( 0, subtypes.length,
435+
i -> collectNonNullableTransientEntities(
436+
nullifier,
437+
subvalues[i],
438+
subPropertyNames[i],
439+
subtypes[i],
440+
subValueNullability[i],
441+
session,
442+
nonNullableTransientEntities
443+
)
444+
);
445+
}
446+
}
447+
448+
return voidFuture();
449+
}
362450

363451
/**
364452
* Disallow instantiation

hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityInsertAction.java

+4
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,8 @@ default CompletionStage<Void> reactiveMakeEntityManaged() {
8787
isVersionIncrementDisabled()
8888
));
8989
}
90+
91+
default CompletionStage<NonNullableTransientDependencies> reactiveFindNonNullableTransientEntities() {
92+
return ForeignKeys.findNonNullableTransientEntities( getPersister().getEntityName(), getInstance(), getState(), isEarlyInsert(), getSession() );
93+
}
9094
}

0 commit comments

Comments
 (0)