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 62ea80cfc048d7a7d6df8a4943a4fdb264eb871a Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sun Feb 15 23:35:15 2026 -0600 Consolidate binder architecture and enable recursive component binding - Merge ComponentPropertyBinder logic into ComponentBinder to resolve circular dependencies. - Enable recursive component binding in ComponentBinder. - Update CompositeIdBinder to use the consolidated ComponentBinder and ComponentUpdater. - Simplify binder wiring in GrailsDomainBinder. - Update and migrate unit tests to verify the consolidated binding logic and recursive capabilities. --- .../org/grails/orm/hibernate/cfg/GrailsDomainBinder.java | 2 +- .../cfg/domainbinding/binder/ComponentBinder.java | 4 ++-- .../cfg/domainbinding/binder/CompositeIdBinder.java | 7 +++++-- .../cfg/domainbinding/ComponentBinderSpec.groovy | 15 +++++++-------- .../cfg/domainbinding/CompositeIdBinderSpec.groovy | 6 +++++- .../cfg/domainbinding/GrailsPropertyBinderSpec.groovy | 2 +- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 0b639d8e0a..d8c716a554 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -210,7 +210,7 @@ public class GrailsDomainBinder manyToOneBinder, propertyFromValueCreator ); - CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder); + CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder, componentUpdater); PropertyBinder propertyBinder = new PropertyBinder(); SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinder); IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java index 818406b9f0..61c481924e 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java @@ -90,7 +90,8 @@ public class ComponentBinder { component.setParentProperty(currentGrailsProp.getName()); continue; } - bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, table, mappings); + var value = bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, table, mappings); + componentUpdater.updateComponent(component, property, currentGrailsProp, value); } return component; @@ -150,7 +151,6 @@ public class ComponentBinder { this.simpleValueBinder.bindSimpleValue(currentGrailsProp, componentProperty, (SimpleValue) value, path); } } - componentUpdater.updateComponent(component, componentProperty, currentGrailsProp, value); return value; } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java index 90b4e415fb..b776560f8f 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java @@ -17,10 +17,12 @@ public class CompositeIdBinder { private final MetadataBuildingContext metadataBuildingContext; private final ComponentBinder componentBinder; + private final ComponentUpdater componentUpdater; - public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, ComponentBinder componentBinder) { + public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, ComponentBinder componentBinder, ComponentUpdater componentUpdater) { this.metadataBuildingContext = metadataBuildingContext; this.componentBinder = componentBinder; + this.componentUpdater = componentUpdater; } @@ -61,7 +63,8 @@ public class CompositeIdBinder { "] is not a valid property!"); } - componentBinder.bindComponentProperty(id, identifierProp, property, root, "", root.getTable(), mappings); + var value = componentBinder.bindComponentProperty(id, identifierProp, property, root, "", root.getTable(), mappings); + componentUpdater.updateComponent(id, identifierProp, property, value); } } } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy index 619364cebf..a28128ee15 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy @@ -58,15 +58,13 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { OneToOneBinder oneToOneBinder = Mock(OneToOneBinder) ManyToOneBinder manyToOneBinder = Mock(ManyToOneBinder) ColumnNameForPropertyAndPathFetcher columnNameFetcher = Mock(ColumnNameForPropertyAndPathFetcher) - ComponentUpdater componentUpdater + ComponentUpdater componentUpdater = Mock(ComponentUpdater) SimpleValueBinder mockSimpleValueBinder = Mock(SimpleValueBinder) @Subject ComponentBinder binder def setup() { - componentUpdater = new ComponentUpdater(propertyFromValueCreator) - binder = new ComponentBinder( getGrailsDomainBinder().getMetadataBuildingContext(), mappingCacheHolder, @@ -126,6 +124,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { component.getRoleName() == Address.name + ".address" 1 * mappingCacheHolder.cacheMapping(associatedEntity) 1 * mockSimpleValueBinder.bindSimpleValue(prop1, embeddedProp, _ as BasicValue, "address") + 1 * componentUpdater.updateComponent(_ as Component, embeddedProp, prop1, _ as Value) } def "should bind simple property"() { @@ -155,7 +154,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { then: 1 * mockSimpleValueBinder.bindSimpleValue(currentGrailsProp, componentProperty, _ as BasicValue, "address") - 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty + 0 * componentUpdater.updateComponent(_, _, _, _) } def "should bind many-to-one property"() { @@ -188,7 +187,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { then: 1 * manyToOneBinder.bindManyToOne(currentGrailsProp, _ as HibernateManyToOne, "address") - 1 * propertyFromValueCreator.createProperty(_ as HibernateManyToOne, currentGrailsProp) >> hibernateProperty + 0 * componentUpdater.updateComponent(_, _, _, _) } def "should bind one-to-one property"() { @@ -225,7 +224,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { then: 1 * oneToOneBinder.bindOneToOne(currentGrailsProp, _ as HibernateOneToOne, "address") - 1 * propertyFromValueCreator.createProperty(_ as HibernateOneToOne, currentGrailsProp) >> hibernateProperty + 0 * componentUpdater.updateComponent(_, _, _, _) } def "should bind enum property"() { @@ -255,7 +254,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { then: 1 * enumTypeBinder.bindEnumType(currentGrailsProp, MyEnum, _ as BasicValue, "address_type_col") - 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty + 0 * componentUpdater.updateComponent(_, _, _, _) } def "should set columns to nullable when component property is nullable"() { @@ -290,7 +289,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec { _ as BasicValue, "address" ) - 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty + 0 * componentUpdater.updateComponent(_, _, _, _) } static class MyEntity {} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy index 15b580db45..15b0032436 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy @@ -13,17 +13,19 @@ import spock.lang.Subject import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder +import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater import org.hibernate.mapping.Value class CompositeIdBinderSpec extends HibernateGormDatastoreSpec { def componentBinder = Mock(ComponentBinder) + def componentUpdater = Mock(ComponentUpdater) @Subject CompositeIdBinder binder def setup() { - binder = new CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), componentBinder) + binder = new CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), componentBinder, componentUpdater) } def "should bind composite id using property names from CompositeIdentity"() { @@ -55,6 +57,7 @@ class CompositeIdBinderSpec extends HibernateGormDatastoreSpec { root.getIdentifierMapper() instanceof Component root.hasEmbeddedIdentifier() 2 * componentBinder.bindComponentProperty(_ as Component, identifierProp, _ as PersistentProperty, root, "", table, mappings) >> Mock(Value) + 2 * componentUpdater.updateComponent(_ as Component, identifierProp, _ as PersistentProperty, _ as Value) } def "should fallback to domainClass composite identity when CompositeIdentity is null"() { @@ -79,6 +82,7 @@ class CompositeIdBinderSpec extends HibernateGormDatastoreSpec { then: 1 * componentBinder.bindComponentProperty(_ as Component, identifierProp, prop1, root, "", table, mappings) >> Mock(Value) + 1 * componentUpdater.updateComponent(_ as Component, identifierProp, prop1, _ as Value) } def "should throw MappingException if no composite properties found"() { diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy index d672fe8e80..5d0141c5b8 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy @@ -109,7 +109,7 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { manyToOneBinder, propertyFromValueCreator ) - CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder) + CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder, componentUpdater); PropertyBinder propertyBinderHelper = new PropertyBinder() SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper) IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder)
