ref #10067 adapt AbstractPersistentCollection to new hibernate version in taxeditor
authorAndreas Müller <a.mueller@bgbm.org>
Tue, 31 May 2022 21:27:26 +0000 (23:27 +0200)
committerAndreas Müller <a.mueller@bgbm.org>
Tue, 31 May 2022 21:27:26 +0000 (23:27 +0200)
eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java

index 6dbfa17a9c010f91e2c656c50bb19db7e91bff2a..18642012387e3e946ff4f92e9640a1eedd385644 100644 (file)
@@ -18,6 +18,7 @@ import java.util.ListIterator;
 import java.util.Map;
 
 import org.hibernate.AssertionFailure;
+import org.hibernate.FlushMode;
 import org.hibernate.HibernateException;
 import org.hibernate.LazyInitializationException;
 import org.hibernate.Session;
@@ -25,19 +26,21 @@ import org.hibernate.collection.spi.PersistentCollection;
 import org.hibernate.engine.internal.ForeignKeys;
 import org.hibernate.engine.spi.CollectionEntry;
 import org.hibernate.engine.spi.EntityEntry;
+import org.hibernate.engine.spi.PersistenceContext;
 import org.hibernate.engine.spi.SessionFactoryImplementor;
 import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
 import org.hibernate.engine.spi.Status;
 import org.hibernate.engine.spi.TypedValue;
 import org.hibernate.internal.CoreLogging;
 import org.hibernate.internal.CoreMessageLogger;
 import org.hibernate.internal.SessionFactoryRegistry;
 import org.hibernate.internal.util.MarkerObject;
-import org.hibernate.internal.util.collections.EmptyIterator;
 import org.hibernate.internal.util.collections.IdentitySet;
 import org.hibernate.persister.collection.CollectionPersister;
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.pretty.MessageHelper;
+import org.hibernate.resource.transaction.spi.TransactionStatus;
 import org.hibernate.type.CompositeType;
 import org.hibernate.type.IntegerType;
 import org.hibernate.type.LongType;
@@ -90,7 +93,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         */
        private static final long serialVersionUID = 7094296207968006972L;
 
-       private transient SessionImplementor session;
+       private transient SharedSessionContractImplementor session;
        private boolean isTempSession = false;
        private boolean initialized;
        private transient List<DelayedOperation> operationQueue;
@@ -104,6 +107,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        // collections detect changes made via their public interface and mark
        // themselves as dirty as a performance optimization
        private boolean dirty;
+       protected boolean elementRemoved;
        private Serializable storedSnapshot;
 
        private String sessionFactoryUuid;
@@ -116,10 +120,18 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        public AbstractPersistentCollection() {
        }
 
-       protected AbstractPersistentCollection(SessionImplementor session) {
+       protected AbstractPersistentCollection(SharedSessionContractImplementor session) {
                this.session = session;
        }
 
+       /**
+        * @deprecated {@link #AbstractPersistentCollection(SharedSessionContractImplementor)} should be used instead.
+        */
+       @Deprecated
+       protected AbstractPersistentCollection(SessionImplementor session) {
+               this( (SharedSessionContractImplementor) session );
+       }
+
        @Override
        public final String getRole() {
                return role;
@@ -140,9 +152,15 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                return dirty;
        }
 
+       @Override
+       public boolean isElementRemoved() {
+               return elementRemoved;
+       }
+
        @Override
        public final void clearDirty() {
                dirty = false;
+               elementRemoved = false;
        }
 
        @Override
@@ -190,7 +208,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                                new LazyInitializationWork<Boolean>() {
                                                        @Override
                                                        public Boolean doWork() {
-                                                               final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+                                                               final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
 
                                                                if ( entry != null ) {
                                                                        final CollectionPersister persister = entry.getLoadedPersister();
@@ -236,7 +254,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        }
 
        private <T> T withTemporarySessionIfNeeded(LazyInitializationWork<T> lazyInitializationWork) {
-               SessionImplementor tempSession = null;
+               SharedSessionContractImplementor tempSession = null;
 
                if ( session == null ) {
                        if ( allowLoadOutsideTransaction ) {
@@ -246,7 +264,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                throwLazyInitializationException( "could not initialize proxy - no Session" );
                        }
                }
-               else if ( !session.isOpen() ) {
+               else if ( !session.isOpenOrWaitingForAutoClose() ) {
                        if ( allowLoadOutsideTransaction ) {
                                tempSession = openTemporarySessionForLoading();
                        }
@@ -263,8 +281,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        }
                }
 
-
-               SessionImplementor originalSession = null;
+               SharedSessionContractImplementor originalSession = null;
                boolean isJTA = false;
 
                if ( tempSession != null ) {
@@ -272,7 +289,6 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        originalSession = session;
                        session = tempSession;
 
-
                        isJTA = session.getTransactionCoordinator().getTransactionCoordinatorBuilder().isJta();
 
                        if ( !isJTA ) {
@@ -284,7 +300,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                ( (Session) session ).beginTransaction();
                        }
 
-                       session.getPersistenceContext().addUninitializedDetachedCollection(
+                       session.getPersistenceContextInternal().addUninitializedDetachedCollection(
                                        session.getFactory().getCollectionPersister( getRole() ),
                                        this
                        );
@@ -312,14 +328,17 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                }
        }
 
-       private SessionImplementor openTemporarySessionForLoading() {
+       private SharedSessionContractImplementor openTemporarySessionForLoading() {
                if ( sessionFactoryUuid == null ) {
                        throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
                }
 
                final SessionFactoryImplementor sf = (SessionFactoryImplementor)
                                SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
-               return (SessionImplementor) sf.openSession();
+               final SharedSessionContractImplementor session = (SharedSessionContractImplementor) sf.openSession();
+               session.getPersistenceContextInternal().setDefaultReadOnly( true );
+               session.setFlushMode( FlushMode.MANUAL );
+               return session;
        }
 
        protected Boolean readIndexExistence(final Object index) {
@@ -337,7 +356,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                        new LazyInitializationWork<Boolean>() {
                                                @Override
                                                public Boolean doWork() {
-                                                       final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+                                                       final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
                                                        final CollectionPersister persister = entry.getLoadedPersister();
                                                        if ( persister.isExtraLazy() ) {
                                                                if ( hasQueuedOperations() ) {
@@ -376,7 +395,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                        new LazyInitializationWork<Boolean>() {
                                                @Override
                                                public Boolean doWork() {
-                                                       final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+                                                       final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
                                                        final CollectionPersister persister = entry.getLoadedPersister();
                                                        if ( persister.isExtraLazy() ) {
                                                                if ( hasQueuedOperations() ) {
@@ -419,7 +438,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
 
                                @Override
                                public Object doWork() {
-                                       final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
+                                       final CollectionEntry entry = session.getPersistenceContextInternal().getCollectionEntry( AbstractPersistentCollection.this );
                                        final CollectionPersister persister = entry.getLoadedPersister();
                                        isExtraLazy = persister.isExtraLazy();
                                        if ( isExtraLazy ) {
@@ -454,7 +473,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        protected boolean isConnectedToSession() {
                return session != null
                                && session.isOpen()
-                               && session.getPersistenceContext().containsCollection( this );
+                               && session.getPersistenceContextInternal().containsCollection( this );
        }
 
        protected boolean isInitialized() {
@@ -509,7 +528,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         */
        @SuppressWarnings({"JavaDoc"})
        protected boolean isInverseCollection() {
-               final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+               final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
                return ce != null && ce.getLoadedPersister().isInverse();
        }
 
@@ -519,11 +538,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         */
        @SuppressWarnings({"JavaDoc"})
        protected boolean isInverseCollectionNoOrphanDelete() {
-               final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
-               return ce != null
-                               &&
-                               ce.getLoadedPersister().isInverse() &&
-                               !ce.getLoadedPersister().hasOrphanDelete();
+               final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
+               if ( ce == null ) {
+                       return false;
+               }
+               final CollectionPersister loadedPersister = ce.getLoadedPersister();
+               return loadedPersister.isInverse() && !loadedPersister.hasOrphanDelete();
        }
 
        /**
@@ -532,10 +552,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         */
        @SuppressWarnings({"JavaDoc"})
        protected boolean isInverseOneToManyOrNoOrphanDelete() {
-               final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
-               return ce != null
-                               && ce.getLoadedPersister().isInverse()
-                               && ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
+               final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
+               if ( ce == null ) {
+                       return false;
+               }
+               final CollectionPersister loadedPersister = ce.getLoadedPersister();
+               return loadedPersister.isInverse() && ( loadedPersister.isOneToMany() || !loadedPersister.hasOrphanDelete() );
        }
 
        /**
@@ -573,6 +595,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                for ( DelayedOperation operation : operationQueue ) {
                        operation.operate();
                }
+               clearOperationQueue();
        }
 
        @Override
@@ -584,11 +607,15 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
 
        @Override
        public void postAction() {
-               operationQueue = null;
+               clearOperationQueue();
                cachedSize = -1;
                clearDirty();
        }
 
+       public final void clearOperationQueue() {
+               operationQueue = null;
+       }
+
        @Override
        public Object getValue() {
                return this;
@@ -610,9 +637,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        public boolean afterInitialize() {
                setInitialized();
                //do this bit after setting initialized to true or it will recurse
-               if ( operationQueue != null ) {
+               if ( hasQueuedOperations() ) {
                        performQueuedOperations();
-                       operationQueue = null;
                        cachedSize = -1;
                        return false;
                }
@@ -685,10 +711,41 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        }
 
        @Override
-       public final boolean unsetSession(SessionImplementor currentSession) {
+       public final boolean unsetSession(SharedSessionContractImplementor currentSession) {
                prepareForPossibleLoadingOutsideTransaction();
                if ( currentSession == this.session ) {
                        if ( !isTempSession ) {
+                               if ( hasQueuedOperations() ) {
+                                       final String collectionInfoString = MessageHelper.collectionInfoString( getRole(), getKey() );
+                                       try {
+                                               final TransactionStatus transactionStatus =
+                                                               session.getTransactionCoordinator().getTransactionDriverControl().getStatus();
+                                               if ( transactionStatus.isOneOf(
+                                                               TransactionStatus.ROLLED_BACK,
+                                                               TransactionStatus.MARKED_ROLLBACK,
+                                                               TransactionStatus.FAILED_COMMIT,
+                                                               TransactionStatus.FAILED_ROLLBACK,
+                                                               TransactionStatus.ROLLING_BACK
+                                               ) ) {
+                                                       // It was due to a rollback.
+                                                       LOG.queuedOperationWhenDetachFromSessionOnRollback( collectionInfoString );
+                                               }
+                                               else {
+                                                       // We don't know why the collection is being detached.
+                                                       // Just log the info.
+                                                       LOG.queuedOperationWhenDetachFromSession( collectionInfoString );
+                                               }
+                                       }
+                                       catch (Exception e) {
+                                               // We don't know why the collection is being detached.
+                                               // Just log the info.
+                                               LOG.queuedOperationWhenDetachFromSession( collectionInfoString );
+                                       }
+                               }
+                               if ( allowLoadOutsideTransaction && !initialized && session.getLoadQueryInfluencers().hasEnabledFilters() ) {
+                                       final String collectionInfoString = MessageHelper.collectionInfoString( getRole(), getKey() );
+                                       LOG.enabledFiltersWhenDetachFromSession( collectionInfoString );
+                               }
                                this.session = null;
                        }
                        return true;
@@ -712,32 +769,29 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
        }
 
        @Override
-       public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
+       public final boolean setCurrentSession(SharedSessionContractImplementor session) throws HibernateException {
                if ( session == this.session ) {
                        return false;
                }
-               else {
-                       if ( this.session != null ) {
-                               final String msg = generateUnexpectedSessionStateMessage( session );
-                               if ( isConnectedToSession() ) {
-                                       throw new HibernateException(
-                                                       "Illegal attempt to associate a collection with two open sessions. " + msg
-                                       );
-                               }
-                               else {
-                                       LOG.logUnexpectedSessionInCollectionNotConnected( msg );
-                                       this.session = session;
-                                       return true;
-                               }
+               else if ( this.session != null ) {
+                       final String msg = generateUnexpectedSessionStateMessage( session );
+                       if ( isConnectedToSession() ) {
+                               throw new HibernateException(
+                                               "Illegal attempt to associate a collection with two open sessions. " + msg
+                               );
                        }
                        else {
-                               this.session = session;
-                               return true;
+                               LOG.logUnexpectedSessionInCollectionNotConnected( msg );
                        }
                }
+               if ( hasQueuedOperations() ) {
+                       LOG.queuedOperationWhenAttachToSession( MessageHelper.collectionInfoString( getRole(), getKey() ) );
+               }
+               this.session = session;
+               return true;
        }
 
-       private String generateUnexpectedSessionStateMessage(SessionImplementor session) {
+       private String generateUnexpectedSessionStateMessage(SharedSessionContractImplementor session) {
                // NOTE: If this.session != null, this.session may be operating on this collection
                // (e.g., by changing this.role, this.key, or even this.session) in a different thread.
 
@@ -754,7 +808,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        sb.append( MessageHelper.collectionInfoString( roleCurrent, keyCurrent ) );
                }
                else {
-                       final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
+                       final CollectionEntry ce = session.getPersistenceContextInternal().getCollectionEntry( this );
                        if ( ce != null ) {
                                sb.append(
                                                MessageHelper.collectionInfoString(
@@ -788,7 +842,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                // AST in ORM 5+, handling this type of condition is either extremely difficult or impossible.  Forcing
                // recreation isn't ideal, but not really any other option in ORM 4.
                // Selecting a type used in where part of update statement
-               // (must match condidion in org.hibernate.persister.collection.BasicCollectionPersister.doUpdateRows).
+               // (must match condition in org.hibernate.persister.collection.BasicCollectionPersister#doUpdateRows).
                // See HHH-9474
                Type whereType;
                if ( persister.hasIndex() ) {
@@ -861,7 +915,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        };
                }
                else {
-                       return EmptyIterator.INSTANCE;
+                       return Collections.emptyIterator();
                }
        }
 
@@ -898,7 +952,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         *
         * @return The session
         */
-       public final SessionImplementor getSession() {
+       public final SharedSessionContractImplementor getSession() {
                return session;
        }
 
@@ -1268,7 +1322,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        Collection oldElements,
                        Collection currentElements,
                        String entityName,
-                       SessionImplementor session) throws HibernateException {
+                       SharedSessionContractImplementor session) throws HibernateException {
 
                // short-circuit(s)
                if ( currentElements.size() == 0 ) {
@@ -1290,9 +1344,10 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
                final java.util.Set currentIds = new HashSet();
                final java.util.Set currentSaving = new IdentitySet();
+               final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
                for ( Object current : currentElements ) {
                        if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
-                               final EntityEntry ee = session.getPersistenceContext().getEntry( current );
+                               final EntityEntry ee = persistenceContext.getEntry( current );
                                if ( ee != null && ee.getStatus() == Status.SAVING ) {
                                        currentSaving.add( current );
                                }
@@ -1341,7 +1396,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                        Collection list,
                        Object entityInstance,
                        String entityName,
-                       SessionImplementor session) {
+                       SharedSessionContractImplementor session) {
 
                if ( entityInstance != null && ForeignKeys.isNotTransient( entityName, entityInstance, null, session ) ) {
                        final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
@@ -1360,6 +1415,26 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                }
        }
 
+       /**
+        * Removes entity entries that have an equal identifier with the incoming entity instance
+        *
+        * @param list The list containing the entity instances
+        * @param entityInstance The entity instance to match elements.
+        * @param entityName The entity name
+        * @param session The session
+        *
+        * @deprecated {@link #identityRemove(Collection, Object, String, SharedSessionContractImplementor)}
+        *             should be used instead.
+        */
+       @Deprecated
+       public static void identityRemove(
+                       Collection list,
+                       Object entityInstance,
+                       String entityName,
+                       SessionImplementor session) {
+               identityRemove( list, entityInstance, entityName, (SharedSessionContractImplementor) session );
+       }
+
        @Override
        public Object getIdentifier(Object entry, int i) {
                throw new UnsupportedOperationException();