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 dfc567747ece06fc08bc59e64f1f9e822786f58b Author: Walter Duque de Estrada <[email protected]> AuthorDate: Tue Mar 3 09:02:27 2026 -0600 refactor CollectionSecondPassBinder --- .../secondpass/CollectionSecondPassBinder.java | 66 +++++++++++++--------- .../CollectionSecondPassBinderSpec.groovy | 41 +++++++------- 2 files changed, 60 insertions(+), 47 deletions(-) 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 6b705fa4d8..27077eb16f 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 @@ -34,6 +34,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyPr import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty; +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity; import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher; import org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder; import org.hibernate.MappingException; @@ -93,7 +94,8 @@ public class CollectionSecondPassBinder { Map<?, ?> persistentClasses, @Nonnull Collection collection) { - PersistentClass associatedClass = bindOrderBy(property, collection, persistentClasses); + PersistentClass associatedClass = resolveAssociatedClass(property, persistentClasses); + bindOrderBy(property, collection, associatedClass); bindOneToManyAssociation(property, associatedClass, collection); applyMultiTenantFilter(property, collection); @@ -217,44 +219,52 @@ public class CollectionSecondPassBinder { collectionForPropertyConfigBinder.bindCollectionForPropertyConfig(collection, property); } - PersistentClass bindOrderBy( - HibernateToManyProperty property, Collection collection, Map<?, ?> persistentClasses) { + private PersistentClass resolveAssociatedClass( + HibernateToManyProperty property, Map<?, ?> persistentClasses) { return Optional.ofNullable(property.getHibernateAssociatedEntity()) .map( referenced -> { - if (referenced.isTablePerHierarchySubclass()) { - String discriminatorColumnName = referenced.getDiscriminatorColumnName(); - Set<String> discSet = referenced.buildDiscriminatorSet(); - String inclause = String.join(",", discSet); - - collection.setWhere(discriminatorColumnName + " in (" + inclause + ")"); - } - PersistentClass associatedClass = (PersistentClass) persistentClasses.get(referenced.getName()); if (associatedClass == null) { throw new MappingException( "Association references unmapped class: " + referenced.getName()); } - - if (property.hasSort()) { - if (!property.isBidirectional() && property instanceof HibernateOneToManyProperty) { - throw new DatastoreConfigurationException( - "Default sort for associations [" - + property.getHibernateOwner().getName() - + "->" - + property.getName() - + "] are not supported with unidirectional one to many relationships."); - } - HibernatePersistentProperty sortBy = - (HibernatePersistentProperty) referenced.getPropertyByName(property.getSort()); - String order = Optional.ofNullable(property.getOrder()).orElse("asc"); - collection.setOrderBy( - orderByClauseBuilder.buildOrderByClause( - sortBy.getName(), associatedClass, collection.getRole(), order)); - } return associatedClass; }) .orElse(null); } + + private void bindOrderBy( + HibernateToManyProperty property, Collection collection, PersistentClass associatedClass) { + if (associatedClass == null) { + return; + } + GrailsHibernatePersistentEntity referenced = property.getHibernateAssociatedEntity(); + + if (referenced.isTablePerHierarchySubclass()) { + String discriminatorColumnName = referenced.getDiscriminatorColumnName(); + Set<String> discSet = referenced.buildDiscriminatorSet(); + String inclause = String.join(",", discSet); + + collection.setWhere(discriminatorColumnName + " in (" + inclause + ")"); + } + + if (property.hasSort()) { + if (!property.isBidirectional() && property instanceof HibernateOneToManyProperty) { + throw new DatastoreConfigurationException( + "Default sort for associations [" + + property.getHibernateOwner().getName() + + "->" + + property.getName() + + "] are not supported with unidirectional one to many relationships."); + } + HibernatePersistentProperty sortBy = + (HibernatePersistentProperty) referenced.getPropertyByName(property.getSort()); + String order = Optional.ofNullable(property.getOrder()).orElse("asc"); + collection.setOrderBy( + orderByClauseBuilder.buildOrderByClause( + sortBy.getName(), associatedClass, collection.getRole(), order)); + } + } } 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 76c011d992..d4501b62a3 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 @@ -58,86 +58,89 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec { def collection = new Bag(getGrailsDomainBinder().getMetadataBuildingContext(), null) collection.setRole("CSPBTestEntityWithMany.items") - def persistentClasses = [:] def associatedPersistentClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) associatedPersistentClass.setEntityName(CSPBAssociatedItem.name) def valueProperty = new org.hibernate.mapping.Property() valueProperty.setName("value") - def simpleValue = new org.hibernate.mapping.BasicValue(getGrailsDomainBinder().getMetadataBuildingContext(), new org.hibernate.mapping.Table("ASSOCIATED_ITEM")) + def simpleValue = new org.hibernate.mapping.BasicValue(getGrailsDomainBinder().getMetadataBuildingContext(), new org.hibernate.mapping.Table("test", "ASSOCIATED_ITEM")) simpleValue.setTypeName("string") def column = new org.hibernate.mapping.Column("VALUE") simpleValue.addColumn(column) valueProperty.setValue(simpleValue) associatedPersistentClass.addProperty(valueProperty) - persistentClasses[CSPBAssociatedItem.name] = associatedPersistentClass property.getMappedForm().setSort("value") property.getMappedForm().setOrder("desc") when: - def result = binder.bindOrderBy(property, collection, persistentClasses) + binder.bindOrderBy(property, collection, associatedPersistentClass) then: collection.getOrderBy() != null - result == associatedPersistentClass } def "test bindOrderBy with unidirectional one-to-many throws exception"() { given: def property = createTestHibernateToManyProperty(CSPBUnidirectionalEntity, "items") as HibernateToManyProperty def collection = new Bag(getGrailsDomainBinder().getMetadataBuildingContext(), null) - def persistentClasses = [:] def associatedPersistentClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) associatedPersistentClass.setEntityName(CSPBAssociatedItem.name) - persistentClasses[CSPBAssociatedItem.name] = associatedPersistentClass property.getMappedForm().setSort("value") when: - binder.bindOrderBy(property, collection, persistentClasses) + binder.bindOrderBy(property, collection, associatedPersistentClass) then: thrown(DatastoreConfigurationException) } - def "test bindOrderBy returns associatedClass even without sort"() { + def "test bindOrderBy does nothing without sort"() { given: def property = createTestHibernateToManyProperty(CSPBTestEntityWithMany, "items") as HibernateToManyProperty def collection = new Bag(getGrailsDomainBinder().getMetadataBuildingContext(), null) - def persistentClasses = [:] def associatedPersistentClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) associatedPersistentClass.setEntityName(CSPBAssociatedItem.name) - persistentClasses[CSPBAssociatedItem.name] = associatedPersistentClass when: - def result = binder.bindOrderBy(property, collection, persistentClasses) + binder.bindOrderBy(property, collection, associatedPersistentClass) then: collection.getOrderBy() == null - result == associatedPersistentClass } - def "test bindOrderBy throws MappingException when class is unmapped"() { + def "test resolveAssociatedClass throws MappingException when class is unmapped"() { given: def property = createTestHibernateToManyProperty(CSPBTestEntityWithMany, "items") as HibernateToManyProperty - def collection = new Bag(getGrailsDomainBinder().getMetadataBuildingContext(), null) def persistentClasses = [:] // Empty map, so CSPBAssociatedItem will be missing when: - binder.bindOrderBy(property, collection, persistentClasses) + binder.resolveAssociatedClass(property, persistentClasses) then: thrown(org.hibernate.MappingException) } + def "test resolveAssociatedClass returns associatedClass"() { + given: + def property = createTestHibernateToManyProperty(CSPBTestEntityWithMany, "items") as HibernateToManyProperty + def associatedPersistentClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) + associatedPersistentClass.setEntityName(CSPBAssociatedItem.name) + def persistentClasses = [(CSPBAssociatedItem.name): associatedPersistentClass] + + when: + def result = binder.resolveAssociatedClass(property, persistentClasses) + + then: + result == associatedPersistentClass + } + def "test bindOrderBy with table per hierarchy subclass"() { given: def property = createTestHibernateToManyProperty(CSPBTestEntityWithMany, "items") as HibernateToManyProperty def collection = new Bag(getGrailsDomainBinder().getMetadataBuildingContext(), null) - def persistentClasses = [:] def associatedPersistentClass = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) associatedPersistentClass.setEntityName(CSPBAssociatedItem.name) - persistentClasses[CSPBAssociatedItem.name] = associatedPersistentClass // Mock GrailsHibernatePersistentEntity behavior for table per hierarchy def referencedEntity = property.getHibernateAssociatedEntity() @@ -151,7 +154,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec { spiedProperty.getHibernateAssociatedEntity() >> spiedReferencedEntity when: - binder.bindOrderBy(spiedProperty, collection, persistentClasses) + binder.bindOrderBy(spiedProperty, collection, associatedPersistentClass) then: collection.getWhere() == "item_type in ('A','B')"
