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 b98c7509c5dae7a4953488f0853275a4f52efef1 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Thu Feb 5 20:21:06 2026 -0600 CollectionBinder --- .../cfg/domainbinding/GrailsPropertyBinder.java | 47 ++++++++++++++++--- .../domainbinding/GrailsPropertyBinderSpec.groovy | 52 ++++++++++++++++++++++ 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinder.java index eed6a7a709..e1503724b1 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinder.java @@ -38,6 +38,10 @@ public class GrailsPropertyBinder { private final ComponentPropertyBinder componentPropertyBinder; private final CollectionBinder collectionBinder; private final PropertyFromValueCreator propertyFromValueCreator; + private final SimpleValueBinder simpleValueBinder; + private final ColumnNameForPropertyAndPathFetcher columnNameForPropertyAndPathFetcher; + private final OneToOneBinder oneToOneBinder; + private final ManyToOneBinder manyToOneBinder; public GrailsPropertyBinder( MetadataBuildingContext metadataBuildingContext, @@ -47,6 +51,31 @@ public class GrailsPropertyBinder { ComponentPropertyBinder componentPropertyBinder, CollectionBinder collectionBinder, PropertyFromValueCreator propertyFromValueCreator) { + this(metadataBuildingContext, + namingStrategy, + collectionHolder, + enumTypeBinder, + componentPropertyBinder, + collectionBinder, + propertyFromValueCreator, + new SimpleValueBinder(namingStrategy), + new ColumnNameForPropertyAndPathFetcher(namingStrategy), + new OneToOneBinder(namingStrategy), + new ManyToOneBinder(namingStrategy)); + } + + protected GrailsPropertyBinder( + MetadataBuildingContext metadataBuildingContext, + PersistentEntityNamingStrategy namingStrategy, + CollectionHolder collectionHolder, + EnumTypeBinder enumTypeBinder, + ComponentPropertyBinder componentPropertyBinder, + CollectionBinder collectionBinder, + PropertyFromValueCreator propertyFromValueCreator, + SimpleValueBinder simpleValueBinder, + ColumnNameForPropertyAndPathFetcher columnNameForPropertyAndPathFetcher, + OneToOneBinder oneToOneBinder, + ManyToOneBinder manyToOneBinder) { this.metadataBuildingContext = metadataBuildingContext; this.namingStrategy = namingStrategy; this.collectionHolder = collectionHolder; @@ -54,6 +83,10 @@ public class GrailsPropertyBinder { this.componentPropertyBinder = componentPropertyBinder; this.collectionBinder = collectionBinder; this.propertyFromValueCreator = propertyFromValueCreator; + this.simpleValueBinder = simpleValueBinder; + this.columnNameForPropertyAndPathFetcher = columnNameForPropertyAndPathFetcher; + this.oneToOneBinder = oneToOneBinder; + this.manyToOneBinder = manyToOneBinder; } public void bindProperty(PersistentClass persistentClass @@ -77,12 +110,12 @@ public class GrailsPropertyBinder { if (currentGrailsProp.isUserButNotCollectionType()) { value = new BasicValue(metadataBuildingContext, table); // No specific binder call needed for this case per original logic - new SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH); + simpleValueBinder.bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH); } else if (collectionType != null) { if (currentGrailsProp.isSerializableType()) { value = new BasicValue(metadataBuildingContext, table); - new SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH);// No specific binder call needed + simpleValueBinder.bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH);// No specific binder call needed } else { // Actual Collection Collection collection = collectionType.create((HibernateToManyProperty) currentGrailsProp, persistentClass, @@ -97,17 +130,17 @@ public class GrailsPropertyBinder { value = new BasicValue(metadataBuildingContext, table); // Apply enumTypeBinder if the created value is a SimpleValue SimpleValue simpleValue = (SimpleValue) value; - String columnName = new ColumnNameForPropertyAndPathFetcher(namingStrategy).getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null); + String columnName = columnNameForPropertyAndPathFetcher.getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null); enumTypeBinder.bindEnumType(currentGrailsProp, currentGrailsProp.getType(), simpleValue, columnName); } else if (currentGrailsProp.isHibernateOneToOne()) { value = new OneToOne(metadataBuildingContext, table, persistentClass); // Apply OneToOneBinder logic - new OneToOneBinder(namingStrategy).bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne)currentGrailsProp, (OneToOne)value, EMPTY_PATH); + oneToOneBinder.bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne)currentGrailsProp, (OneToOne)value, EMPTY_PATH); } else if(currentGrailsProp.isHibernateManyToOne()) { value = new ManyToOne(metadataBuildingContext, table); // Apply ManyToOneBinder logic - new ManyToOneBinder(namingStrategy).bindManyToOne((Association)currentGrailsProp, (ManyToOne)value, EMPTY_PATH); + manyToOneBinder.bindManyToOne((Association)currentGrailsProp, (ManyToOne)value, EMPTY_PATH); } else if (currentGrailsProp instanceof Embedded) { value = new Component(metadataBuildingContext, persistentClass); @@ -117,7 +150,7 @@ public class GrailsPropertyBinder { // work out what type of relationship it is and bind value else { // Default BasicValue value = new BasicValue(metadataBuildingContext, table); - new SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH); + simpleValueBinder.bindSimpleValue(currentGrailsProp, null,(SimpleValue) value, EMPTY_PATH); } // After creating the value and applying binders (where applicable), create and add the property. @@ -127,4 +160,4 @@ public class GrailsPropertyBinder { persistentClass.addProperty(property); } } -} +} \ No newline at end of file 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 b8fddef382..ab4324a6a4 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 @@ -278,6 +278,58 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { oneToOne.referencedEntityName == bookEntity.name } + void "should use binders from protected constructor"() { + given: + def metadataBuildingContext = Mock(org.hibernate.boot.spi.MetadataBuildingContext) + def namingStrategy = Mock(org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy) + // CollectionHolder is a Java record (final), so we instantiate it + def collectionHolder = new org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder(new HashMap<Class<?>, org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType>()) + def enumTypeBinder = Mock(EnumTypeBinder) + def componentPropertyBinder = Mock(ComponentPropertyBinder) + def collectionBinder = Mock(CollectionBinder) + def propertyFromValueCreator = Mock(PropertyFromValueCreator) + def simpleValueBinder = Mock(SimpleValueBinder) + def columnNameForPropertyAndPathFetcher = Mock(ColumnNameForPropertyAndPathFetcher) + def oneToOneBinder = Mock(OneToOneBinder) + def manyToOneBinder = Mock(ManyToOneBinder) + + def propertyBinder = new GrailsPropertyBinder( + metadataBuildingContext, + namingStrategy, + collectionHolder, + enumTypeBinder, + componentPropertyBinder, + collectionBinder, + propertyFromValueCreator, + simpleValueBinder, + columnNameForPropertyAndPathFetcher, + oneToOneBinder, + manyToOneBinder + ) + + def mappings = Mock(org.hibernate.boot.spi.InFlightMetadataCollector) + metadataBuildingContext.getMetadataCollector() >> mappings + + def rootClass = new RootClass(metadataBuildingContext) + def currentGrailsProp = Mock(GrailsHibernatePersistentProperty) + def table = new org.hibernate.mapping.Table("TEST_TABLE") + rootClass.setTable(table) + def owner = Mock(org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity) + + currentGrailsProp.getHibernateOwner() >> owner + owner.getMappedForm() >> new org.grails.orm.hibernate.cfg.Mapping() + currentGrailsProp.getType() >> String.class + currentGrailsProp.getName() >> "title" + + propertyFromValueCreator.createProperty(_ as org.hibernate.mapping.Value, currentGrailsProp) >> new Property() + + when: + propertyBinder.bindProperty(rootClass, mappings, "sessionFactory", currentGrailsProp) + + then: + 1 * simpleValueBinder.bindSimpleValue(currentGrailsProp, null, _ as SimpleValue, "") + } + }
