From 6880f73ae0ad05515b217c799dac3c05c86fbc9d Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 13 Nov 2024 10:19:46 +0100 Subject: [PATCH] HHH-18842 CollectionType.replace() breaks if target is PersistentCollection, but not instance of Collection --- .../collection/spi/PersistentArrayHolder.java | 4 +++ .../hibernate/engine/internal/Cascade.java | 14 +++++++++-- .../org/hibernate/type/CollectionType.java | 25 +++++++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java index 4ade676b92..426ca5b88d 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java @@ -7,6 +7,7 @@ package org.hibernate.collection.spi; import java.io.Serializable; import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -92,6 +93,9 @@ public class PersistentArrayHolder extends AbstractPersistentCollection { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { final Object[] sn = (Object[]) snapshot; final Object[] arr = (Object[]) array; + if ( arr.length == 0 ) { + return Arrays.asList( sn ); + } final ArrayList result = new ArrayList(); Collections.addAll( result, sn ); for ( int i=0; i persistentCollection; + if ( child instanceof PersistentCollection pc ) { + persistentCollection = pc; + } + else { + persistentCollection = eventSource.getPersistenceContext() + .getCollectionHolder( child ); + } + final boolean deleteOrphans = style.hasOrphanDelete() && action.deleteOrphans() && elemType instanceof EntityType - && child instanceof PersistentCollection persistentCollection + && persistentCollection != null // a newly instantiated collection can't have orphans && !persistentCollection.isNewlyInstantiated(); @@ -617,7 +627,7 @@ public final class Cascade { // 1. newly instantiated collections // 2. arrays (we can't track orphans for detached arrays) final String entityName = collectionType.getAssociatedEntityName( eventSource.getFactory() ); - deleteOrphans( eventSource, entityName, (PersistentCollection) child ); + deleteOrphans( eventSource, entityName, persistentCollection ); if ( traceEnabled ) { LOG.tracev( "Done deleting orphans for collection: {0}", collectionType.getRole() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java index 5ddeeae38a..0e7409fb01 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java @@ -24,6 +24,7 @@ import org.hibernate.Incubating; import org.hibernate.Internal; import org.hibernate.MappingException; import org.hibernate.collection.spi.AbstractPersistentCollection; +import org.hibernate.collection.spi.PersistentArrayHolder; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.CollectionEntry; import org.hibernate.engine.spi.CollectionKey; @@ -634,11 +635,31 @@ public abstract class CollectionType extends AbstractType implements Association if ( target == null ) { return null; } - if ( target instanceof PersistentCollection ) { - final Collection collection = (Collection) target; + if ( target instanceof Collection collection ) { collection.clear(); return collection; } + else if ( target instanceof Map map ) { + map.clear(); + return map; + } + else { + final PersistenceContext persistenceContext = session.getPersistenceContext(); + final PersistentCollection collectionHolder = persistenceContext + .getCollectionHolder( target ); + if ( collectionHolder != null ) { + if ( collectionHolder instanceof PersistentArrayHolder persistentArrayHolder ) { + persistenceContext.removeCollectionHolder( target ); + persistentArrayHolder.beginRead(); + persistentArrayHolder.injectLoadedState( persistenceContext.getCollectionEntry( collectionHolder ).getLoadedPersister().getAttributeMapping(), null ); + persistentArrayHolder.endRead(); + persistentArrayHolder.dirty(); + persistenceContext.addCollectionHolder( collectionHolder ); + return persistentArrayHolder.getArray(); + } + } + } + return null; } if ( !Hibernate.isInitialized( original ) ) {