HHH-16117 Querying entity with collection in Embeddable causes 'A collection with cascade=all-delete-orphan was no longer referenced by the owning entity instance'

This commit is contained in:
Andrea Boriero 2023-01-31 11:19:02 +01:00 committed by Christian Beikov
parent 7b6d158245
commit 974afe26f0
5 changed files with 112 additions and 13 deletions

View File

@ -18,10 +18,13 @@ import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.EventSource;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.AttributeMappingsList;
import org.hibernate.persister.entity.EntityPersister;
import static org.hibernate.engine.internal.Versioning.getVersion;
@ -148,20 +151,69 @@ public abstract class AbstractEntityInsertAction extends EntityAction {
protected void addCollectionsByKeyToPersistenceContext(PersistenceContext persistenceContext, Object[] objects) {
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()
)
final AttributeMapping attributeMapping = getPersister().getAttributeMapping( i );
if ( attributeMapping.isEmbeddedAttributeMapping() ) {
visitEmbeddedAttributeMapping(
attributeMapping.asEmbeddedAttributeMapping(),
objects[i],
persistenceContext
);
persistenceContext.addCollectionByKey( collectionKey, persistentCollection );
}
else if ( attributeMapping.isPluralAttributeMapping() ) {
addCollectionKey(
attributeMapping.asPluralAttributeMapping(),
objects[i],
persistenceContext
);
}
}
}
private void visitEmbeddedAttributeMapping(
EmbeddedAttributeMapping attributeMapping,
Object object,
PersistenceContext persistenceContext) {
if ( object != null ) {
final AttributeMappingsList attributeMappings = attributeMapping.getEmbeddableTypeDescriptor().getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attribute = attributeMappings.get( i );
if ( attribute.isPluralAttributeMapping() ) {
addCollectionKey(
attribute.asPluralAttributeMapping(),
attribute.getPropertyAccess().getGetter().get( object ),
persistenceContext
);
}
else if ( attribute.isEmbeddedAttributeMapping() ) {
visitEmbeddedAttributeMapping(
attribute.asEmbeddedAttributeMapping(),
attribute.getPropertyAccess().getGetter().get( object ),
persistenceContext
);
}
}
}
}
private void addCollectionKey(
PluralAttributeMapping pluralAttributeMapping,
Object o,
PersistenceContext persistenceContext) {
if ( o instanceof PersistentCollection ) {
final CollectionPersister collectionPersister = pluralAttributeMapping.getCollectionDescriptor();
final CollectionKey collectionKey = new CollectionKey(
collectionPersister,
( (AbstractEntityPersister) getPersister() ).getCollectionKey(
collectionPersister,
getInstance(),
persistenceContext.getEntry( getInstance() ),
getSession()
)
);
persistenceContext.addCollectionByKey(
collectionKey,
(PersistentCollection<?>) o
);
}
}

View File

@ -100,7 +100,7 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
final EntityPersister persister = getPersister();
final Object instance = getInstance();
persister.insert( id, getState(), instance, session );
PersistenceContext persistenceContext = session.getPersistenceContextInternal();
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
final EntityEntry entry = persistenceContext.getEntry( instance );
if ( entry == null ) {
throw new AssertionFailure( "possible non-threadsafe access to session" );

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.metamodel.mapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.sql.results.graph.DatabaseSnapshotContributor;
import org.hibernate.sql.results.graph.Fetchable;
@ -92,4 +93,30 @@ public interface AttributeMapping
return this;
}
/**
* A utility method to avoid casting explicitly to PluralAttributeMapping
*
* @return PluralAttributeMapping if this is an instance of PluralAttributeMapping otherwise {@code null}
*/
default PluralAttributeMapping asPluralAttributeMapping() {
return null;
}
default boolean isPluralAttributeMapping() {
return false;
}
/**
* A utility method to avoid casting explicitly to EmbeddedAttributeMapping
*
* @return EmbeddedAttributeMapping if this is an instance of EmbeddedAttributeMapping otherwise {@code null}
*/
default EmbeddedAttributeMapping asEmbeddedAttributeMapping(){
return null;
}
default boolean isEmbeddedAttributeMapping(){
return false;
}
}

View File

@ -175,4 +175,14 @@ public interface PluralAttributeMapping
SqlAstCreationState creationState) {
getCollectionDescriptor().applyWhereRestrictions( predicateConsumer, tableGroup, useQualifier, creationState );
}
@Override
default PluralAttributeMapping asPluralAttributeMapping() {
return this;
}
@Override
default boolean isPluralAttributeMapping() {
return true;
}
}

View File

@ -437,4 +437,14 @@ public class EmbeddedAttributeMapping
}
return parentInjectionAttributePropertyAccess;
}
@Override
public EmbeddedAttributeMapping asEmbeddedAttributeMapping() {
return this;
}
@Override
public boolean isEmbeddedAttributeMapping() {
return true;
}
}