HHH-15258 Orphan removal for OneToMany relations is broken when used with GenerationType.IDENTITY

This commit is contained in:
Andrea Boriero 2022-05-10 12:17:59 +02:00 committed by Andrea Boriero
parent 1a94bcc4a2
commit 2af19a6278
5 changed files with 86 additions and 103 deletions

View File

@ -7,16 +7,22 @@
package org.hibernate.action.internal;
import org.hibernate.LockMode;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.internal.NonNullableTransientDependencies;
import org.hibernate.engine.internal.Nullability;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
/**
@ -132,6 +138,27 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
getPersister(),
isVersionIncrementDisabled
);
if ( isEarlyInsert() ) {
final SharedSessionContractImplementor session = getSession();
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
Object[] objects = getState();
for ( int i = 0; i < objects.length; i++ ) {
if ( objects[i] instanceof PersistentCollection<?> ) {
final PersistentCollection<?> persistentCollection = (PersistentCollection<?>) objects[i];
final CollectionPersister collectionPersister = ( (PluralAttributeMapping) getPersister().getAttributeMapping( i ) ).getCollectionDescriptor();
final CollectionKey collectionKey = new CollectionKey(
collectionPersister,
( (AbstractEntityPersister) getPersister() ).getCollectionKey(
collectionPersister,
getInstance(),
persistenceContext.getEntry( getInstance() ),
getSession()
)
);
persistenceContext.addCollectionByKey( collectionKey, persistentCollection );
}
}
}
}
/**

View File

@ -1614,7 +1614,7 @@ public abstract class AbstractEntityPersister
}
protected Object getCollectionKey(
public Object getCollectionKey(
CollectionPersister persister,
Object owner,
EntityEntry ownerEntry,

View File

@ -6,16 +6,22 @@
*/
package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.collection.CollectionLoadingLogger;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -85,6 +91,56 @@ public abstract class AbstractCollectionInitializer implements CollectionInitial
}
}
protected void resolveInstance(RowProcessingState rowProcessingState, boolean isEager) {
if ( collectionKey != null ) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey );
if ( loadingEntry != null ) {
collectionInstance = loadingEntry.getCollectionInstance();
return;
}
final PersistentCollection<?> existing = persistenceContext.getCollection( collectionKey );
if ( existing != null ) {
collectionInstance = existing;
return;
}
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics<?, ?> collectionSemantics = collectionDescriptor.getCollectionSemantics();
final Object key = collectionKey.getKey();
collectionInstance = collectionSemantics.instantiateWrapper(
key,
collectionDescriptor,
session
);
parentAccess.registerResolutionListener(
owner -> collectionInstance.setOwner( owner )
);
persistenceContext.addUninitializedCollection(
collectionDescriptor,
collectionInstance,
key
);
if ( isEager ) {
persistenceContext.addNonLazyCollection( collectionInstance );
}
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) {
session.getPersistenceContext().addCollectionHolder( collectionInstance );
}
}
}
protected boolean isAttributeAssignableToConcreteDescriptor() {
if ( parentAccess instanceof EntityInitializer ) {
final AbstractEntityPersister concreteDescriptor = (AbstractEntityPersister) ( (EntityInitializer) parentAccess ).getConcreteDescriptor();

View File

@ -6,18 +6,11 @@
*/
package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/**
@ -35,49 +28,7 @@ public class DelayedCollectionInitializer extends AbstractCollectionInitializer
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey );
if ( loadingEntry != null ) {
collectionInstance = loadingEntry.getCollectionInstance();
return;
}
final PersistentCollection<?> existing = persistenceContext.getCollection( collectionKey );
if ( existing != null ) {
collectionInstance = existing;
return;
}
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics<?, ?> collectionSemantics = collectionDescriptor.getCollectionSemantics();
final Object key = collectionKey.getKey();
collectionInstance = collectionSemantics.instantiateWrapper(
key,
collectionDescriptor,
session
);
parentAccess.registerResolutionListener(
owner -> collectionInstance.setOwner( owner )
);
persistenceContext.addUninitializedCollection(
collectionDescriptor,
collectionInstance,
key
);
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) {
session.getPersistenceContext().addCollectionHolder( collectionInstance );
}
}
resolveInstance( rowProcessingState, false );
}
@Override

View File

@ -6,18 +6,11 @@
*/
package org.hibernate.sql.results.graph.collection.internal;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/**
@ -35,51 +28,7 @@ public class SelectEagerCollectionInitializer extends AbstractCollectionInitiali
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts()
.findLoadingCollectionEntry( collectionKey );
if ( loadingEntry != null ) {
collectionInstance = loadingEntry.getCollectionInstance();
return;
}
final PersistentCollection<?> existing = persistenceContext.getCollection( collectionKey );
if ( existing != null ) {
collectionInstance = existing;
return;
}
final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor();
final CollectionSemantics<?, ?> collectionSemantics = collectionDescriptor.getCollectionSemantics();
final Object key = collectionKey.getKey();
collectionInstance = collectionSemantics.instantiateWrapper(
key,
collectionDescriptor,
session
);
parentAccess.registerResolutionListener(
owner -> collectionInstance.setOwner( owner )
);
persistenceContext.addUninitializedCollection(
collectionDescriptor,
collectionInstance,
key
);
persistenceContext.addNonLazyCollection( collectionInstance );
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) {
session.getPersistenceContext().addCollectionHolder( collectionInstance );
}
}
resolveInstance( rowProcessingState, true );
}
@Override