You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/04/06 19:16:54 UTC

(grails-core) 04/12: H7: renames and removing unused arguments in collection second pass binders

This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit b7f518e471321414e8c7212bbd81f80fb8e21968
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Apr 4 20:36:05 2026 -0500

    H7: renames and removing unused arguments in collection second pass binders
---
 .../cfg/domainbinding/binder/CollectionBinder.java | 16 ++---
 .../secondpass/CollectionKeyBinder.java            |  2 +-
 .../secondpass/CollectionKeyColumnUpdater.java     | 20 +++----
 .../CollectionMultiTenantFilterBinder.java         | 70 ----------------------
 .../secondpass/CollectionSecondPassBinder.java     | 38 +++++-------
 ...ava => HibernateToManyEntityOrderByBinder.java} |  6 +-
 .../secondpass/ListSecondPassBinder.java           |  2 +-
 ...mentBinder.java => ManyToOneElementBinder.java} |  6 +-
 .../secondpass/MapSecondPassBinder.java            |  2 +-
 .../domainbinding/secondpass/SetSecondPass.java    |  2 +-
 .../ToManyEntityMultiTenantFilterBinder.java       | 64 ++++++++++++++++++++
 .../secondpass/CollectionKeyBinderSpec.groovy      | 10 ++--
 .../CollectionKeyColumnUpdaterSpec.groovy          | 30 +++-------
 .../CollectionSecondPassBinderSpec.groovy          | 22 ++++---
 ... HibernateToManyEntityOrderByBinderSpec.groovy} |  4 +-
 ...ec.groovy => ManyToOneElementBinderSpec.groovy} |  6 +-
 ...ToManyEntityMultiTenantFilterBinderSpec.groovy} |  6 +-
 17 files changed, 141 insertions(+), 165 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
index c1f69d73e3..2cfe6e43ca 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
@@ -30,6 +30,7 @@ import org.grails.orm.hibernate.cfg.GrailsHibernateUtil;
 import org.grails.orm.hibernate.cfg.JoinTable;
 import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy;
 import org.grails.orm.hibernate.cfg.PropertyConfig;
+import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher;
 import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder;
 import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
@@ -40,14 +41,14 @@ import org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalMapEle
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalOneToManyLinker;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyColumnUpdater;
-import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionMultiTenantFilterBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionEntityOrderByBinder;
+import org.grails.orm.hibernate.cfg.domainbinding.secondpass.HibernateToManyEntityOrderByBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionSecondPassBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionWithJoinTableBinder;
+import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ToManyEntityMultiTenantFilterBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.DependentKeyValueBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPass;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPassBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ManyToManyElementBinder;
+import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ManyToOneElementBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPass;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPassBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.PrimaryKeyValueCreator;
@@ -55,7 +56,6 @@ import org.grails.orm.hibernate.cfg.domainbinding.secondpass.SetSecondPass;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyInverseValuesBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehavior;
-import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher;
 import org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver;
 import org.grails.orm.hibernate.cfg.domainbinding.util.NamespaceNameExtractor;
 import org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher;
@@ -116,11 +116,11 @@ public class CollectionBinder {
                         new PrimaryKeyValueCreator(metadataBuildingContext))),
                 new UnidirectionalOneToManyBinder(collectionWithJoinTableBinder, mappings),
                 collectionWithJoinTableBinder,
-                collectionForPropertyConfigBinder,
                 new BidirectionalMapElementBinder(manyToOneBinder, collectionForPropertyConfigBinder),
-                new ManyToManyElementBinder(manyToOneBinder, collectionForPropertyConfigBinder),
-                new CollectionEntityOrderByBinder(),
-                new CollectionMultiTenantFilterBinder(new DefaultColumnNameFetcher(namingStrategy)));
+                new ManyToOneElementBinder(manyToOneBinder, collectionForPropertyConfigBinder),
+                new HibernateToManyEntityOrderByBinder(),
+                new ToManyEntityMultiTenantFilterBinder(new DefaultColumnNameFetcher(namingStrategy))
+        );
         this.listSecondPassBinder = new ListSecondPassBinder(
                 metadataBuildingContext, namingStrategy, collectionSecondPassBinder, simpleValueColumnBinder, mappings);
         this.mapSecondPassBinder = new MapSecondPassBinder(
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinder.java
index ac047ecc67..29e89480f4 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinder.java
@@ -50,7 +50,7 @@ public class CollectionKeyBinder {
     }
 
     /** Creates the {@link DependantValue} key, sets it on the collection, and binds it. */
-    public DependantValue bind(HibernateToManyProperty property, PersistentClass ownerClass) {
+    public DependantValue bind(HibernateToManyProperty property) {
         Collection collection = property.getCollection();
         DependantValue key = primaryKeyValueCreator.createPrimaryKeyValue(collection);
         collection.setKey(key);
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdater.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdater.java
index 3c5e3fe875..850b482c45 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdater.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdater.java
@@ -21,7 +21,6 @@ package org.grails.orm.hibernate.cfg.domainbinding.secondpass;
 import java.util.Objects;
 
 import org.hibernate.mapping.DependantValue;
-import org.hibernate.mapping.PersistentClass;
 
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
 
@@ -36,19 +35,18 @@ public class CollectionKeyColumnUpdater {
     }
 
     /** Creates the key, sets it on the collection, and updates its columns. */
-    public void bind(HibernateToManyProperty property, PersistentClass ownerClass) {
-        DependantValue key = collectionKeyBinder.bind(property, ownerClass);
-        forceNullableAndCheckUpdatable(key, property);
-    }
-
-    /** Force nullable and check updatable. */
-    public void forceNullableAndCheckUpdatable(DependantValue key, HibernateToManyProperty property) {
+    public void bind(HibernateToManyProperty property) {
+        DependantValue key = collectionKeyBinder.bind(property);
         key.getColumns().stream().filter(Objects::nonNull).forEach(column -> column.setNullable(true));
-
-        long unidirectionalCount = property.getHibernateOwner().getPersistentPropertiesToBind().stream()
-                .filter(p -> p instanceof HibernateToManyProperty association && !association.isBidirectional())
+        long unidirectionalCount = property.getHibernateOwner()
+                .getPersistentPropertiesToBind()
+                .stream()
+                .filter(HibernateToManyProperty.class::isInstance)
+                .map(HibernateToManyProperty.class::cast)
+                .filter(p -> !p.isBidirectional())
                 .count();
 
         key.setUpdateable(unidirectionalCount <= 1);
     }
+
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java
deleted file mode 100644
index f8be0b2338..0000000000
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    https://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.grails.orm.hibernate.cfg.domainbinding.secondpass;
-
-import java.util.Collections;
-import java.util.Optional;
-
-import org.hibernate.mapping.Collection;
-
-import org.grails.datastore.mapping.model.config.GormProperties;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
-import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher;
-
-/** Applies multi-tenant filters to a collection based on the associated entity's tenancy. */
-public class CollectionMultiTenantFilterBinder {
-
-    private final DefaultColumnNameFetcher defaultColumnNameFetcher;
-
-    /** Creates a new {@link CollectionMultiTenantFilterBinder} instance. */
-    public CollectionMultiTenantFilterBinder(DefaultColumnNameFetcher defaultColumnNameFetcher) {
-        this.defaultColumnNameFetcher = defaultColumnNameFetcher;
-    }
-
-    /** Applies the multi-tenant filter to the collection if the associated entity is multi-tenant. */
-    public void bind(HibernateToManyProperty property) {
-        if (property instanceof HibernateToManyEntityProperty entityProperty) {
-            GrailsHibernatePersistentEntity referenced = entityProperty.getHibernateAssociatedEntity();
-            if (entityProperty.isOneToMany() && referenced.isMultiTenant()) {
-                String filterCondition = referenced.getMultiTenantFilterCondition(defaultColumnNameFetcher);
-                if (filterCondition != null) {
-                    Collection collection = property.getCollection();
-                    if (entityProperty.isUnidirectionalOneToMany()) {
-                        collection.addManyToManyFilter(
-                                GormProperties.TENANT_IDENTITY,
-                                filterCondition,
-                                true,
-                                Collections.emptyMap(),
-                                Collections.emptyMap());
-                    } else {
-                        collection.addFilter(
-                                GormProperties.TENANT_IDENTITY,
-                                filterCondition,
-                                true,
-                                Collections.emptyMap(),
-                                Collections.emptyMap());
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
index 8b2cb7d749..7da9e6d599 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
@@ -18,18 +18,14 @@
  */
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass;
 
-import java.util.Map;
-
 import jakarta.annotation.Nonnull;
 
 import org.hibernate.mapping.Collection;
-import org.hibernate.mapping.PersistentClass;
 
-import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyCollectionProperty;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyCollectionProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
 
 /**
@@ -38,40 +34,35 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyPrope
 @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
 public class CollectionSecondPassBinder {
 
-    private final CollectionEntityOrderByBinder collectionEntityOrderByBinder;
-    private final CollectionMultiTenantFilterBinder collectionMultiTenantFilterBinder;
+    private final HibernateToManyEntityOrderByBinder hibernateToManyEntityOrderByBinder;
+    private final ToManyEntityMultiTenantFilterBinder hibernateToManyEntityMultiTenantFilterBinder;
     private final CollectionKeyColumnUpdater collectionKeyColumnUpdater;
     private final BidirectionalMapElementBinder bidirectionalMapElementBinder;
-    private final ManyToManyElementBinder manyToManyElementBinder;
+    private final ManyToOneElementBinder manyToManyElementBinder;
     private final UnidirectionalOneToManyBinder unidirectionalOneToManyBinder;
     private final CollectionWithJoinTableBinder collectionWithJoinTableBinder;
-    private final CollectionForPropertyConfigBinder collectionForPropertyConfigBinder;
 
     public CollectionSecondPassBinder(
             CollectionKeyColumnUpdater collectionKeyColumnUpdater,
             UnidirectionalOneToManyBinder unidirectionalOneToManyBinder,
             CollectionWithJoinTableBinder collectionWithJoinTableBinder,
-            CollectionForPropertyConfigBinder collectionForPropertyConfigBinder,
             BidirectionalMapElementBinder bidirectionalMapElementBinder,
-            ManyToManyElementBinder manyToManyElementBinder,
-            CollectionEntityOrderByBinder collectionEntityOrderByBinder,
-            CollectionMultiTenantFilterBinder collectionMultiTenantFilterBinder) {
+            ManyToOneElementBinder manyToManyElementBinder,
+            HibernateToManyEntityOrderByBinder hibernateToManyEntityOrderByBinder,
+            ToManyEntityMultiTenantFilterBinder hibernateToManyEntityMultiTenantFilterBinder) {
         this.collectionKeyColumnUpdater = collectionKeyColumnUpdater;
         this.unidirectionalOneToManyBinder = unidirectionalOneToManyBinder;
         this.collectionWithJoinTableBinder = collectionWithJoinTableBinder;
-        this.collectionForPropertyConfigBinder = collectionForPropertyConfigBinder;
         this.bidirectionalMapElementBinder = bidirectionalMapElementBinder;
         this.manyToManyElementBinder = manyToManyElementBinder;
-        this.collectionEntityOrderByBinder = collectionEntityOrderByBinder;
-        this.collectionMultiTenantFilterBinder = collectionMultiTenantFilterBinder;
+        this.hibernateToManyEntityOrderByBinder = hibernateToManyEntityOrderByBinder;
+        this.hibernateToManyEntityMultiTenantFilterBinder = hibernateToManyEntityMultiTenantFilterBinder;
     }
 
-    public void bindCollectionSecondPass(@Nonnull HibernateToManyProperty property, Map<?, ?> persistentClasses) {
-
-        PersistentClass ownerClass = property.getHibernateOwner().getPersistentClass();
+    public void bindCollectionSecondPass(@Nonnull HibernateToManyProperty property) {
 
         if (property instanceof HibernateToManyEntityProperty entityProperty) {
-            collectionEntityOrderByBinder.bind(entityProperty);
+            hibernateToManyEntityOrderByBinder.bind(entityProperty);
             if (entityProperty.isManyToMany() && entityProperty.isBidirectional()) {
                 manyToManyElementBinder.bind((HibernateManyToManyProperty) entityProperty);
             } else if (entityProperty.isBidirectionalToManyMap() && entityProperty.isBidirectional()) {
@@ -79,12 +70,13 @@ public class CollectionSecondPassBinder {
             } else if (entityProperty.isOneToMany() && entityProperty.isUnidirectionalOneToMany()) {
                 unidirectionalOneToManyBinder.bind((HibernateOneToManyProperty) entityProperty);
             }
+            hibernateToManyEntityMultiTenantFilterBinder.bind(entityProperty);
         } else if (property instanceof HibernateToManyCollectionProperty collectionProperty &&
                 collectionProperty.supportsJoinColumnMapping()) {
             collectionWithJoinTableBinder.bindCollectionWithJoinTable(collectionProperty);
         }
-        collectionMultiTenantFilterBinder.bind(property);
-        collectionKeyColumnUpdater.bind(property, ownerClass);
+
+        collectionKeyColumnUpdater.bind(property);
         Collection collection = property.getCollection();
         collection.setSorted(property.isSorted());
         collection.setCacheConcurrencyStrategy(property.getCacheUsage());
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinder.java
similarity index 95%
rename from grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java
rename to grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinder.java
index ab9a343b9a..e666cf5d70 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinder.java
@@ -32,13 +32,13 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentP
 import org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder;
 
 /** Binds the order-by clause and discriminator where condition to a collection. */
-public class CollectionEntityOrderByBinder {
+public class HibernateToManyEntityOrderByBinder {
 
     private final OrderByClauseBuilder orderByClauseBuilder;
     private final CollectionForPropertyConfigBinder collectionForPropertyConfigBinder;
 
-    /** Creates a new {@link CollectionEntityOrderByBinder} instance. */
-    public CollectionEntityOrderByBinder() {
+    /** Creates a new {@link HibernateToManyEntityOrderByBinder} instance. */
+    public HibernateToManyEntityOrderByBinder() {
         this.orderByClauseBuilder = new OrderByClauseBuilder();
         this.collectionForPropertyConfigBinder = new CollectionForPropertyConfigBinder();
     }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
index a8d5ad97f2..f4006cb0b0 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
@@ -71,7 +71,7 @@ public class ListSecondPassBinder {
     public void bindListSecondPass(@Nonnull HibernateToManyProperty property, Map<?, ?> persistentClasses) {
 
         List list = (List) property.getCollection();
-        collectionSecondPassBinder.bindCollectionSecondPass(property, persistentClasses);
+        collectionSecondPassBinder.bindCollectionSecondPass(property);
         String columnName = property.getIndexColumnName(namingStrategy);
         final boolean isManyToMany = property instanceof HibernateManyToManyProperty;
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinder.java
similarity index 93%
rename from grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinder.java
rename to grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinder.java
index 43408eedd1..8ff7a7ecdb 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinder.java
@@ -28,13 +28,13 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyP
 import static org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder.EMPTY_PATH;
 
 /** Binds the element of a bidirectional many-to-many association. */
-public class ManyToManyElementBinder {
+public class ManyToOneElementBinder {
 
     private final ManyToOneBinder manyToOneBinder;
     private final CollectionForPropertyConfigBinder collectionForPropertyConfigBinder;
 
-    /** Creates a new {@link ManyToManyElementBinder} instance. */
-    public ManyToManyElementBinder(
+    /** Creates a new {@link ManyToOneElementBinder} instance. */
+    public ManyToOneElementBinder(
             ManyToOneBinder manyToOneBinder, CollectionForPropertyConfigBinder collectionForPropertyConfigBinder) {
         this.manyToOneBinder = manyToOneBinder;
         this.collectionForPropertyConfigBinder = collectionForPropertyConfigBinder;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java
index 940bb23c45..4c45197026 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java
@@ -67,7 +67,7 @@ public class MapSecondPassBinder {
 
     public void bindMapSecondPass(@Nonnull HibernateToManyProperty property, Map<?, ?> persistentClasses) {
         org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) property.getCollection();
-        collectionSecondPassBinder.bindCollectionSecondPass(property, persistentClasses);
+        collectionSecondPassBinder.bindCollectionSecondPass(property);
 
         String type = property.getIndexColumnType("string");
         String columnName1 = property.getIndexColumnName(namingStrategy);
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/SetSecondPass.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/SetSecondPass.java
index 67c79edaed..70755effe2 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/SetSecondPass.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/SetSecondPass.java
@@ -47,7 +47,7 @@ public class SetSecondPass implements org.hibernate.boot.spi.SecondPass, GrailsS
 
     @Override
     public void doSecondPass(Map persistentClasses) throws MappingException {
-        collectionSecondPassBinder.bindCollectionSecondPass(property, persistentClasses);
+        collectionSecondPassBinder.bindCollectionSecondPass(property);
         createCollectionKeys(property.getCollection());
     }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinder.java
new file mode 100644
index 0000000000..bdee3d6e97
--- /dev/null
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinder.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.grails.orm.hibernate.cfg.domainbinding.secondpass;
+
+import java.util.Collections;
+
+import org.hibernate.mapping.Collection;
+
+import org.grails.datastore.mapping.model.config.GormProperties;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher;
+
+/** Applies multi-tenant filters to a collection based on the associated entity's tenancy. */
+public class ToManyEntityMultiTenantFilterBinder {
+
+    private final DefaultColumnNameFetcher defaultColumnNameFetcher;
+
+    /** Creates a new {@link ToManyEntityMultiTenantFilterBinder} instance. */
+    public ToManyEntityMultiTenantFilterBinder(DefaultColumnNameFetcher defaultColumnNameFetcher) {
+        this.defaultColumnNameFetcher = defaultColumnNameFetcher;
+    }
+
+    /** Applies the multi-tenant filter to the collection if the associated entity is multi-tenant. */
+    public void bind(HibernateToManyEntityProperty entityProperty) {
+        var referenced = entityProperty.getHibernateAssociatedEntity();
+        if (entityProperty.isOneToMany() && referenced.isMultiTenant()) {
+            String filterCondition = referenced.getMultiTenantFilterCondition(defaultColumnNameFetcher);
+            if (filterCondition != null) {
+                Collection collection = entityProperty.getCollection();
+                if (entityProperty.isUnidirectionalOneToMany()) {
+                    collection.addManyToManyFilter(
+                            GormProperties.TENANT_IDENTITY,
+                            filterCondition,
+                            true,
+                            Collections.emptyMap(),
+                            Collections.emptyMap());
+                } else {
+                    collection.addFilter(
+                            GormProperties.TENANT_IDENTITY,
+                            filterCondition,
+                            true,
+                            Collections.emptyMap(),
+                            Collections.emptyMap());
+                }
+            }
+        }
+    }
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy
index 5ee5db7273..c8e2cc1fbd 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy
@@ -119,7 +119,7 @@ class CollectionKeyBinderSpec extends HibernateGormDatastoreSpec {
         property.getHibernateInverseSide().getHibernateOwner().setPersistentClass(associatedClass)
 
         when:
-        binder.bind(property, ownerClass)
+        binder.bind(property)
 
         then:
         collection.isInverse()
@@ -134,7 +134,7 @@ class CollectionKeyBinderSpec extends HibernateGormDatastoreSpec {
         property.setCollection(collection)
 
         when:
-        binder.bind(property, ownerClass)
+        binder.bind(property)
 
         then:
         collection.getKey().getColumnSpan() > 0
@@ -149,7 +149,7 @@ class CollectionKeyBinderSpec extends HibernateGormDatastoreSpec {
         property.setCollection(collection)
 
         when:
-        binder.bind(property, ownerClass)
+        binder.bind(property)
 
         then:
         collection.getKey().getTypeName() == "long"
@@ -165,7 +165,7 @@ class CollectionKeyBinderSpec extends HibernateGormDatastoreSpec {
         property.setCollection(collection)
 
         when:
-        binder.bind(property, ownerClass)
+        binder.bind(property)
 
         then:
         collection.getKey().getColumnSpan() > 0
@@ -187,7 +187,7 @@ class CollectionKeyBinderSpec extends HibernateGormDatastoreSpec {
         property.setCollection(collection)
 
         when:
-        def key = binder.bind(property, ownerClass)
+        def key = binder.bind(property)
 
         then:
         key.isSorted()
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdaterSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdaterSpec.groovy
index 88d0b53740..417319cf34 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdaterSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyColumnUpdaterSpec.groovy
@@ -24,7 +24,6 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersi
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty
 import org.hibernate.mapping.Column
 import org.hibernate.mapping.DependantValue
-import org.hibernate.mapping.RootClass
 import spock.lang.Subject
 
 class CollectionKeyColumnUpdaterSpec extends HibernateGormDatastoreSpec {
@@ -52,41 +51,25 @@ class CollectionKeyColumnUpdaterSpec extends HibernateGormDatastoreSpec {
         (getPersistentEntity(ownerClass) as GrailsHibernatePersistentEntity).getPropertyByName(name) as HibernateToManyProperty
     }
 
-    def "bind delegates to collectionKeyBinder and forces nullability"() {
+    def "bind delegates to collectionKeyBinder and forces nullability and updateability"() {
         given:
         def property = propertyFor(CKCUOwnerOne)
-        def ownerClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext())
         def column = new Column("test_col")
         column.setNullable(false)
-        def key = Mock(DependantValue) {
-            getColumns() >> [column]
-        }
-
-        when:
-        updater.bind(property, ownerClass)
-
-        then:
-        1 * collectionKeyBinder.bind(property, ownerClass) >> key
-        column.isNullable()
-    }
-
-    def "forceNullableAndCheckUpdatable sets updateable true when only one unidirectional"() {
-        given:
-        def property = propertyFor(CKCUOwnerOne)
-        def column = new Column("test_col")
         def key = new DependantValue(getGrailsDomainBinder().getMetadataBuildingContext(), null, null)
         key.addColumn(column)
         key.setUpdateable(false)
 
         when:
-        updater.forceNullableAndCheckUpdatable(key, property)
+        updater.bind(property)
 
         then:
-        key.isUpdateable()
+        1 * collectionKeyBinder.bind(property) >> key
         column.isNullable()
+        key.isUpdateable()
     }
 
-    def "forceNullableAndCheckUpdatable sets updateable false when multiple unidirectional"() {
+    def "bind sets updateable false when multiple unidirectional"() {
         given:
         def property = propertyFor(CKCUOwnerMany, "items1")
         def column = new Column("test_col")
@@ -95,9 +78,10 @@ class CollectionKeyColumnUpdaterSpec extends HibernateGormDatastoreSpec {
         key.setUpdateable(true)
 
         when:
-        updater.forceNullableAndCheckUpdatable(key, property)
+        updater.bind(property)
 
         then:
+        1 * collectionKeyBinder.bind(property) >> key
         !key.isUpdateable()
         column.isNullable()
     }
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
index c687c46504..16c5fa2b2e 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
@@ -66,7 +66,15 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         def svcb = new SimpleValueColumnBinder()
         def cku = new CollectionKeyColumnUpdater(new CollectionKeyBinder(botml, dkvb, svcb, pkvc))
 
-        binder = new CollectionSecondPassBinder(cku, uotmb, cwjtb, cfpcb, mockBidirectionalMapElementBinder, new ManyToManyElementBinder(mtob, cfpcb), new CollectionEntityOrderByBinder(), new CollectionMultiTenantFilterBinder(dcnf))
+        binder = new CollectionSecondPassBinder(
+                cku,
+                uotmb,
+                cwjtb,
+                mockBidirectionalMapElementBinder,
+                new ManyToOneElementBinder(mtob, cfpcb),
+                new HibernateToManyEntityOrderByBinder(),
+                new ToManyEntityMultiTenantFilterBinder(dcnf)
+        )
     }
 
     protected HibernatePersistentProperty createTestHibernateToManyProperty(Class<?> domainClass, String propertyName) {
@@ -86,7 +94,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         property.getCollection() != null
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
@@ -101,7 +109,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         hibernateFirstPass()
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
@@ -118,7 +126,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         hibernateFirstPass()
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
@@ -136,7 +144,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         hibernateFirstPass()
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
@@ -152,7 +160,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         hibernateFirstPass()
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
@@ -168,7 +176,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         hibernateFirstPass()
 
         when: "Binding second pass"
-        binder.bindCollectionSecondPass(property, [:])
+        binder.bindCollectionSecondPass(property)
 
         then:
         noExceptionThrown()
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinderSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy
rename to grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinderSpec.groovy
index dee029c6e8..451b03febd 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/HibernateToManyEntityOrderByBinderSpec.groovy
@@ -32,10 +32,10 @@ import org.hibernate.mapping.RootClass
 import org.hibernate.mapping.Table
 import spock.lang.Subject
 
-class CollectionEntityOrderByBinderSpec extends HibernateGormDatastoreSpec {
+class HibernateToManyEntityOrderByBinderSpec extends HibernateGormDatastoreSpec {
 
     @Subject
-    CollectionEntityOrderByBinder binder = new CollectionEntityOrderByBinder()
+    HibernateToManyEntityOrderByBinder binder = new HibernateToManyEntityOrderByBinder()
 
 
     void setupSpec() {
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinderSpec.groovy
similarity index 94%
rename from grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinderSpec.groovy
rename to grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinderSpec.groovy
index 15a25f2714..aacc98ef4b 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToManyElementBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ManyToOneElementBinderSpec.groovy
@@ -32,10 +32,10 @@ import org.hibernate.mapping.ManyToOne
 import org.hibernate.mapping.Table
 import spock.lang.Subject
 
-class ManyToManyElementBinderSpec extends HibernateGormDatastoreSpec {
+class ManyToOneElementBinderSpec extends HibernateGormDatastoreSpec {
 
     @Subject
-    ManyToManyElementBinder binder
+    ManyToOneElementBinder binder
 
     void setupSpec() {
         manager.addAllDomainClasses([
@@ -54,7 +54,7 @@ class ManyToManyElementBinderSpec extends HibernateGormDatastoreSpec {
         def svb = new SimpleValueBinder(mbc, ns, je)
         def citmto = new CompositeIdentifierToManyToOneBinder(mbc, ns, je)
         def mtob = new ManyToOneBinder(mbc, ns, svb, new ManyToOneValuesBinder(), citmto)
-        binder = new ManyToManyElementBinder(mtob, new CollectionForPropertyConfigBinder())
+        binder = new ManyToOneElementBinder(mtob, new CollectionForPropertyConfigBinder())
     }
 
     private HibernateManyToManyProperty propertyFor(Class ownerClass, String name = "items") {
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinderSpec.groovy
similarity index 95%
rename from grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinderSpec.groovy
rename to grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinderSpec.groovy
index 61125fc891..c1e18f04d5 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ToManyEntityMultiTenantFilterBinderSpec.groovy
@@ -31,10 +31,10 @@ import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher
 import org.hibernate.mapping.Bag
 import spock.lang.Subject
 
-class CollectionMultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec {
+class ToManyEntityMultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec {
 
     @Subject
-    CollectionMultiTenantFilterBinder binder
+    ToManyEntityMultiTenantFilterBinder binder
 
     void setupSpec() {
         manager.addAllDomainClasses([
@@ -55,7 +55,7 @@ class CollectionMultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec {
 
     void setup() {
         def ns = getGrailsDomainBinder().getNamingStrategy()
-        binder = new CollectionMultiTenantFilterBinder(new DefaultColumnNameFetcher(ns, new BackticksRemover()))
+        binder = new ToManyEntityMultiTenantFilterBinder(new DefaultColumnNameFetcher(ns, new BackticksRemover()))
     }
 
     private HibernateToManyProperty propertyFor(Class ownerClass, String name = "items") {