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

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

commit 4db915f661e1f01d9eafb72e20bc162874c36f16
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Wed Feb 11 21:31:15 2026 -0600

     Now delegate to getChildEntities
---
 .../cfg/GrailsHibernatePersistentEntity.java       | 133 ++++++++++++---------
 .../secondpass/CollectionSecondPassBinder.java     |  36 ++----
 .../cfg/GrailsHibernatePersistentEntitySpec.groovy | 114 +++++++++++-------
 3 files changed, 157 insertions(+), 126 deletions(-)

diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
index 1e59ac83cd..65900d3935 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
@@ -1,64 +1,66 @@
 package org.grails.orm.hibernate.cfg;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-import jakarta.annotation.Nonnull;
-
-import org.hibernate.boot.spi.InFlightMetadataCollector;
-
-import org.grails.datastore.mapping.model.PersistentEntity;
-import org.grails.datastore.mapping.model.PersistentProperty;
-import org.grails.datastore.mapping.model.config.GormProperties;
-import 
org.grails.orm.hibernate.cfg.domainbinding.ConfigureDerivedPropertiesConsumer;
-import org.grails.orm.hibernate.cfg.domainbinding.DefaultColumnNameFetcher;
-import org.grails.orm.hibernate.cfg.domainbinding.NamespaceNameExtractor;
+ 
+ import java.util.Collection;
+ import java.util.List;
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.util.Set;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+ 
+ import jakarta.annotation.Nonnull;
+ 
+ import org.hibernate.boot.spi.InFlightMetadataCollector;
+ 
+ import org.grails.datastore.mapping.model.PersistentEntity;
+ import org.grails.datastore.mapping.model.PersistentProperty;
+ import org.grails.datastore.mapping.model.config.GormProperties;
+ import 
org.grails.orm.hibernate.cfg.domainbinding.ConfigureDerivedPropertiesConsumer;
+ import org.grails.orm.hibernate.cfg.domainbinding.DefaultColumnNameFetcher;
+ import org.grails.orm.hibernate.cfg.domainbinding.NamespaceNameExtractor;
+
+ import static 
org.grails.orm.hibernate.cfg.GrailsDomainBinder.JPA_DEFAULT_DISCRIMINATOR_TYPE;
 
 /**
- * Common interface for Hibernate persistent entities
- */
-public interface GrailsHibernatePersistentEntity extends PersistentEntity {
-    Mapping getMappedForm();
-
-
-    @Nonnull default GrailsHibernatePersistentEntity getHibernateRootEntity() {
-        return  (GrailsHibernatePersistentEntity) getRootEntity();
-    }
-
-    default Mapping getRootMapping() {
-        return getHibernateRootEntity().getMappedForm();
-    }
-
-    default boolean isTablePerHierarchySubclass() {
-        Mapping rootMapping = getRootMapping();
-        return !this.isRoot() && (rootMapping == null || 
rootMapping.getTablePerHierarchy());
-    }
-
-    default java.util.Set<String> buildDiscriminatorSet() {
-        java.util.Set<String> theSet = new java.util.HashSet<>();
-
-        String discriminator = getDiscriminatorValue();
-        Mapping rootMapping = getRootMapping();
-        String quote = "'";
-        if (rootMapping != null && rootMapping.getDatasources() != null) {
-            DiscriminatorConfig discriminatorConfig = 
rootMapping.getDiscriminator();
-            if(discriminatorConfig != null && discriminatorConfig.getType() != 
null && !discriminatorConfig.getType().equals("string"))
-                quote = "";
-        }
-        theSet.add(quote + discriminator + quote);
-
-        final java.util.Collection<PersistentEntity> childEntities = 
getMappingContext().getDirectChildEntities(this);
-        for (PersistentEntity subClass : childEntities) {
-            if (subClass instanceof GrailsHibernatePersistentEntity) {
-                theSet.addAll(((GrailsHibernatePersistentEntity) 
subClass).buildDiscriminatorSet());
-            }
-        }
-        return theSet;
-    }
-
-    @Override
-    GrailsHibernatePersistentProperty getIdentity();
+  * Common interface for Hibernate persistent entities
+  */
+ public interface GrailsHibernatePersistentEntity extends PersistentEntity {
+     Mapping getMappedForm();
+ 
+ 
+     @Nonnull default GrailsHibernatePersistentEntity getHibernateRootEntity() 
{
+         return  (GrailsHibernatePersistentEntity) getRootEntity();
+     }
+ 
+     default Mapping getRootMapping() {
+         return getHibernateRootEntity().getMappedForm();
+     }
+ 
+     default boolean isTablePerHierarchySubclass() {
+         Mapping rootMapping = getRootMapping();
+         return !this.isRoot() && (rootMapping == null || 
rootMapping.getTablePerHierarchy());
+     }
+ 
+     default Set<String> buildDiscriminatorSet() {
+         String quote = Optional.ofNullable(getRootMapping())
+                 .filter(m -> m.getDatasources() != null)
+                 .map(Mapping::getDiscriminator)
+                 .filter(config -> config.getType() != null && 
!config.getType().equals("string"))
+                 .map(config -> "")
+                 .orElse("'");
+ 
+         String quotedDiscriminator = quote + getDiscriminatorValue() + quote;
+ 
+         return Stream.concat(
+                 Stream.of(quotedDiscriminator),
+                 getChildEntities().stream()
+                         
.map(GrailsHibernatePersistentEntity::buildDiscriminatorSet)
+                         .flatMap(Collection::stream)
+         ).collect(Collectors.toSet());
+     }
+ 
+     @Override
+     GrailsHibernatePersistentProperty getIdentity();
 
     @Override
     GrailsHibernatePersistentProperty[] getCompositeIdentity();
@@ -103,6 +105,10 @@ public interface GrailsHibernatePersistentEntity extends 
PersistentEntity {
     @Override
     GrailsHibernatePersistentProperty getVersion();
 
+    default List<GrailsHibernatePersistentEntity> getChildEntities() {
+        return getChildEntities(getDataSourceName());
+    }
+
     default List<GrailsHibernatePersistentEntity> getChildEntities(String 
dataSourceName) {
         return getMappingContext()
                 .getDirectChildEntities(this)
@@ -146,5 +152,16 @@ public interface GrailsHibernatePersistentEntity extends 
PersistentEntity {
 
     }
 
+     default String getDiscriminatorColumnName() {
+        return Optional.ofNullable(getRootMapping())
+                .map(Mapping::getDiscriminator)
+                
.map(GrailsHibernatePersistentEntity::resolveDiscriminatorValue)
+                .orElse(JPA_DEFAULT_DISCRIMINATOR_TYPE);
+
+     }
+
+    private static String resolveDiscriminatorValue(DiscriminatorConfig 
discriminatorConfig) {
+        return discriminatorConfig.getColumn() != null ? 
discriminatorConfig.getColumn().getName() : discriminatorConfig.getFormula();
+    }
 }
 
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 84c0ff8d52..79477f0b66 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
@@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
+import java.util.Set;
 
 import static org.grails.orm.hibernate.cfg.GrailsDomainBinder.*;
 
@@ -91,24 +92,9 @@ public class CollectionSecondPassBinder {
         if (collection.isOneToMany()) {
 
             if (referenced != null && 
referenced.isTablePerHierarchySubclass()) {
-                Mapping rootMapping = referenced.getRootMapping();
-                //TODO FIXME
-                String discriminatorColumnName = 
JPA_DEFAULT_DISCRIMINATOR_TYPE;
-
-                if (rootMapping != null) {
-                    DiscriminatorConfig discriminatorConfig = 
rootMapping.getDiscriminator();
-                    if(discriminatorConfig != null) {
-                        final ColumnConfig discriminatorColumn = 
discriminatorConfig.getColumn();
-                        if (discriminatorColumn != null) {
-                            discriminatorColumnName = 
discriminatorColumn.getName();
-                        }
-                        if (discriminatorConfig.getFormula() != null) {
-                            discriminatorColumnName = 
discriminatorConfig.getFormula();
-                        }
-                    }
-                }
+                String discriminatorColumnName = 
referenced.getDiscriminatorColumnName();
                 //NOTE: this will build the set for the in clause if it has 
sublcasses
-                java.util.Set<String> discSet = 
referenced.buildDiscriminatorSet();
+                Set<String> discSet = referenced.buildDiscriminatorSet();
                 String inclause = String.join(",", discSet);
 
                 collection.setWhere(discriminatorColumnName + " in (" + 
inclause + ")");
@@ -149,7 +135,7 @@ public class CollectionSecondPassBinder {
         }
 
         // setup the primary key references
-        DependantValue key = createPrimaryKeyValue(mappings, 
(GrailsHibernatePersistentProperty) property, collection, persistentClasses);
+        DependantValue key = createPrimaryKeyValue(mappings, property, 
collection, persistentClasses);
 
         // link a bidirectional relationship
         if (property.isBidirectional()) {
@@ -162,7 +148,7 @@ public class CollectionSecondPassBinder {
 
             } else if ((otherSide instanceof ManyToMany) || 
java.util.Map.class.isAssignableFrom(property.getType())) {
 
-                bindDependentKeyValue((GrailsHibernatePersistentProperty) 
property, key, mappings, sessionFactoryBeanName);
+                bindDependentKeyValue(property, key, mappings, 
sessionFactoryBeanName);
 
             }
 
@@ -176,7 +162,7 @@ public class CollectionSecondPassBinder {
 
             } else {
 
-                bindDependentKeyValue((GrailsHibernatePersistentProperty) 
property, key, mappings, sessionFactoryBeanName);
+                bindDependentKeyValue(property, key, mappings, 
sessionFactoryBeanName);
 
             }
 
@@ -184,11 +170,9 @@ public class CollectionSecondPassBinder {
         collection.setKey(key);
 
         // get cache config
-        if (propConfig != null) {
-            CacheConfig cacheConfig = propConfig.getCache();
-            if (cacheConfig != null) {
-                collection.setCacheConcurrencyStrategy(cacheConfig.getUsage());
-            }
+        CacheConfig cacheConfig = propConfig.getCache();
+        if (cacheConfig != null) {
+            collection.setCacheConcurrencyStrategy(cacheConfig.getUsage());
         }
 
         // if we have a many-to-many
@@ -282,7 +266,7 @@ public class CollectionSecondPassBinder {
             }
 
             if (isEnum) {
-                new 
EnumTypeBinder().bindEnumType((GrailsHibernatePersistentProperty) property, 
referencedType, element, columnName);
+                new EnumTypeBinder().bindEnumType(property, referencedType, 
element, columnName);
             }
             else {
 
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy
index 1f7421afe2..05a8e59329 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntitySpec.groovy
@@ -2,6 +2,15 @@ package org.grails.orm.hibernate.cfg
 
 import grails.gorm.annotation.Entity
 import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.grails.datastore.mapping.model.PersistentProperty
+import org.grails.datastore.mapping.model.types.TenantId
+import 
org.grails.orm.hibernate.cfg.domainbinding.ConfigureDerivedPropertiesConsumer
+import org.grails.orm.hibernate.cfg.domainbinding.DefaultColumnNameFetcher
+import org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory
+import org.hibernate.boot.spi.InFlightMetadataCollector
+import spock.lang.Specification
+import org.grails.datastore.mapping.model.MappingContext
 
 class GrailsHibernatePersistentEntitySpec extends HibernateGormDatastoreSpec {
 
@@ -24,68 +33,51 @@ class GrailsHibernatePersistentEntitySpec extends 
HibernateGormDatastoreSpec {
         given:
         GrailsHibernatePersistentEntity entity = getPersistentEntity(Simple) 
as GrailsHibernatePersistentEntity
 
-        when:
-        Set<String> result = entity.buildDiscriminatorSet()
-
-        then:
-        result == ["'org.grails.orm.hibernate.cfg.Simple'"] as Set
+        expect:
+        entity.buildDiscriminatorSet() == 
["'org.grails.orm.hibernate.cfg.Simple'"] as Set
     }
 
     void "test buildDiscriminatorSet with custom discriminator value"() {
         given:
         GrailsHibernatePersistentEntity entity = 
getPersistentEntity(CustomDiscriminator) as GrailsHibernatePersistentEntity
 
-        when:
-        Set<String> result = entity.buildDiscriminatorSet()
-
-        then:
-        result == ["'custom_val'"] as Set
+        expect:
+        entity.buildDiscriminatorSet() == ["'custom_val'"] as Set
     }
 
     void "test buildDiscriminatorSet with numeric discriminator type"() {
         given:
         GrailsHibernatePersistentEntity entity = 
getPersistentEntity(NumericDiscriminator) as GrailsHibernatePersistentEntity
 
-        when:
-        Set<String> result = entity.buildDiscriminatorSet()
-
-        then:
-        result == ["1"] as Set
+        expect:
+        entity.buildDiscriminatorSet() == ["1"] as Set
     }
 
     void "test buildDiscriminatorSet with hierarchy"() {
         given:
-        GrailsHibernatePersistentEntity entity = getPersistentEntity(Vehicle) 
as GrailsHibernatePersistentEntity
-
-        when:
-        Set<String> result = entity.buildDiscriminatorSet()
+        GrailsHibernatePersistentEntity vehicle = getPersistentEntity(Vehicle) 
as GrailsHibernatePersistentEntity
 
-        then:
-        result == ["'VEHICLE'", "'CAR'", "'TRUCK'"] as Set
+        expect:
+        vehicle.buildDiscriminatorSet() == ["'VEHICLE'", "'CAR'", "'TRUCK'"] 
as Set
     }
 
     void "test getHibernateRootEntity and getRootMapping"() {
         given:
-        GrailsHibernatePersistentEntity vehicle = getPersistentEntity(Vehicle) 
as GrailsHibernatePersistentEntity
         GrailsHibernatePersistentEntity car = getPersistentEntity(Car) as 
GrailsHibernatePersistentEntity
 
         expect:
-        car.hibernateRootEntity == vehicle
-        car.rootMapping == vehicle.mappedForm
-        vehicle.hibernateRootEntity == vehicle
-        vehicle.rootMapping == vehicle.mappedForm
+        car.getHibernateRootEntity().javaClass == Vehicle
+        car.getRootMapping().discriminator.value == "VEHICLE"
     }
 
     void "test isTablePerHierarchySubclass"() {
         given:
         GrailsHibernatePersistentEntity vehicle = getPersistentEntity(Vehicle) 
as GrailsHibernatePersistentEntity
         GrailsHibernatePersistentEntity car = getPersistentEntity(Car) as 
GrailsHibernatePersistentEntity
-        GrailsHibernatePersistentEntity simple = getPersistentEntity(Simple) 
as GrailsHibernatePersistentEntity
 
         expect:
         !vehicle.isTablePerHierarchySubclass()
         car.isTablePerHierarchySubclass()
-        !simple.isTablePerHierarchySubclass()
     }
 
     void "test getDiscriminatorValue"() {
@@ -95,9 +87,9 @@ class GrailsHibernatePersistentEntitySpec extends 
HibernateGormDatastoreSpec {
         GrailsHibernatePersistentEntity simple = getPersistentEntity(Simple) 
as GrailsHibernatePersistentEntity
 
         expect:
-        vehicle.discriminatorValue == "VEHICLE"
-        car.discriminatorValue == "CAR"
-        simple.discriminatorValue == "org.grails.orm.hibernate.cfg.Simple"
+        vehicle.getDiscriminatorValue() == "VEHICLE"
+        car.getDiscriminatorValue() == "CAR"
+        simple.getDiscriminatorValue() == "org.grails.orm.hibernate.cfg.Simple"
     }
 
     void "test getPersistentPropertiesToBind"() {
@@ -121,29 +113,33 @@ class GrailsHibernatePersistentEntitySpec extends 
HibernateGormDatastoreSpec {
 
         then:
         children.size() == 2
-        children.any { it.name == Car.name }
-        children.any { it.name == Truck.name }
+        children.any { it.javaClass == Car }
+        children.any { it.javaClass == Truck }
     }
 
     void "test isComponentPropertyNullable"() {
         given:
-        GrailsHibernatePersistentEntity addressOwner = 
getPersistentEntity(AddressOwner) as GrailsHibernatePersistentEntity
-        def addressProp = addressOwner.getPropertyByName("address")
+        GrailsHibernatePersistentEntity owner = 
getPersistentEntity(AddressOwner) as GrailsHibernatePersistentEntity
+        def addressProp = owner.getPropertyByName("address")
 
         expect:
-        addressOwner.isComponentPropertyNullable(addressProp) == false
+        owner.isComponentPropertyNullable(addressProp) == false
     }
 
     void "test getMultiTenantFilterCondition"() {
         given:
-        GrailsHibernatePersistentEntity entity = 
Spy(getPersistentEntity(Person)) as GrailsHibernatePersistentEntity
-        def tenantIdProp = 
Mock(org.grails.datastore.mapping.model.types.TenantId)
+        GrailsHibernatePersistentEntity entity = 
Spy(HibernatePersistentEntity, constructorArgs: [Person, getMappingContext()])
+        def tenantIdProp = Stub(TenantId)
+        tenantIdProp.getName() >> "tenantId"
         entity.getTenantId() >> tenantIdProp
-        def fetcher = 
Mock(org.grails.orm.hibernate.cfg.domainbinding.DefaultColumnNameFetcher)
-        fetcher.getDefaultColumnName(tenantIdProp) >> "tenant_id"
+        def fetcher = Stub(DefaultColumnNameFetcher, constructorArgs: 
[Stub(org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy)])
+        fetcher.getDefaultColumnName(_) >> "tenant_id_col"
 
-        expect:
-        entity.getMultiTenantFilterCondition(fetcher) == ":tenantId = 
tenant_id"
+        when:
+        def condition = entity.getMultiTenantFilterCondition(fetcher)
+
+        then:
+        condition == ":tenantId = tenant_id_col"
     }
 
     void "test getSchema and getCatalog"() {
@@ -175,6 +171,40 @@ class GrailsHibernatePersistentEntitySpec extends 
HibernateGormDatastoreSpec {
         then:
         entities.every { it.dataSourceName == "customDS" }
     }
+
+    void "test buildDiscriminatorSet with dataSourceName"() {
+        given:
+        def context = getMappingContext()
+        GrailsHibernatePersistentEntity vehicle = 
Spy(HibernatePersistentEntity, constructorArgs: [Vehicle, context])
+        GrailsHibernatePersistentEntity car = Spy(HibernatePersistentEntity, 
constructorArgs: [Car, context])
+        GrailsHibernatePersistentEntity truck = Spy(HibernatePersistentEntity, 
constructorArgs: [Truck, context])
+
+        // Mock discriminator values
+        vehicle.getDiscriminatorValue() >> "VEHICLE"
+        car.getDiscriminatorValue() >> "CAR"
+        truck.getDiscriminatorValue() >> "TRUCK"
+        
+        // Ensure child Spies don't try to call real buildDiscriminatorSet if 
it's too complex, 
+        // but here we want to test the recursion.
+        car.getChildEntities(_) >> []
+        truck.getChildEntities(_) >> []
+
+        when: "Testing for DS1"
+        vehicle.setDataSourceName("DS1")
+        vehicle.getChildEntities("DS1") >> [car]
+        Set<String> result1 = vehicle.buildDiscriminatorSet()
+
+        then:
+        result1 == ["'VEHICLE'", "'CAR'"] as Set
+
+        when: "Testing for DS2"
+        vehicle.setDataSourceName("DS2")
+        vehicle.getChildEntities("DS2") >> [truck]
+        Set<String> result2 = vehicle.buildDiscriminatorSet()
+
+        then:
+        result2 == ["'VEHICLE'", "'TRUCK'"] as Set
+    }
 }
 
 @Entity

Reply via email to