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/02/09 03:38:36 UTC
(grails-core) 01/20: GrailsDomainBinder
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 869d405d6d249524e202410a33825b6397edd42e
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Feb 6 17:28:08 2026 -0600
GrailsDomainBinder
---
.../orm/hibernate/cfg/GrailsDomainBinder.java | 3 +-
.../cfg/domainbinding/GrailsPropertyBinder.java | 13 +--
.../domainbinding/GrailsPropertyBinderSpec.groovy | 96 +++++++++++++++-------
3 files changed, 73 insertions(+), 39 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 83a848bb36..031465217d 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
@@ -694,7 +694,8 @@ public class GrailsDomainBinder
for (GrailsHibernatePersistentProperty currentGrailsProp : domainClass.getPersistentPropertiesToBind()) {
- grailsPropertyBinder.bindProperty(persistentClass, mappings, sessionFactoryBeanName, currentGrailsProp);
+ var value = grailsPropertyBinder.bindProperty(persistentClass, mappings, sessionFactoryBeanName, currentGrailsProp);
+ persistentClass.addProperty(propertyFromValueCreator.createProperty(value, currentGrailsProp));
}
new NaturalIdentifierBinder().bindNaturalIdentifier(domainClass.getMappedForm(), persistentClass);
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 12bcf99a15..604b123e91 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
@@ -17,7 +17,6 @@ import org.hibernate.mapping.Component;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.PersistentClass;
-import org.hibernate.mapping.Property;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
@@ -31,12 +30,10 @@ public class GrailsPropertyBinder {
private static final Logger LOG = LoggerFactory.getLogger(GrailsPropertyBinder.class);
private final MetadataBuildingContext metadataBuildingContext;
- private final PersistentEntityNamingStrategy namingStrategy;
private final CollectionHolder collectionHolder;
private final EnumTypeBinder enumTypeBinder;
private final ComponentPropertyBinder componentPropertyBinder;
private final CollectionBinder collectionBinder;
- private final PropertyFromValueCreator propertyFromValueCreator;
private final SimpleValueBinder simpleValueBinder;
private final ColumnNameForPropertyAndPathFetcher columnNameForPropertyAndPathFetcher;
private final OneToOneBinder oneToOneBinder;
@@ -56,7 +53,6 @@ public class GrailsPropertyBinder {
enumTypeBinder,
componentPropertyBinder,
collectionBinder,
- propertyFromValueCreator,
new SimpleValueBinder(namingStrategy),
new ColumnNameForPropertyAndPathFetcher(namingStrategy),
new OneToOneBinder(namingStrategy),
@@ -70,25 +66,22 @@ public class GrailsPropertyBinder {
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;
this.enumTypeBinder = enumTypeBinder;
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
+ public Value bindProperty(PersistentClass persistentClass
, @Nonnull InFlightMetadataCollector mappings
, String sessionFactoryBeanName
, @Nonnull GrailsHibernatePersistentProperty currentGrailsProp) {
@@ -154,7 +147,7 @@ public class GrailsPropertyBinder {
// After creating the value and applying binders (where applicable), create and add the property.
// This is now done once at the end of the consolidated block.
- Property property = propertyFromValueCreator.createProperty(value, currentGrailsProp);
- persistentClass.addProperty(property);
+
+ return value;
}
}
\ 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 ab4324a6a4..4552bc65f9 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
@@ -6,10 +6,31 @@ import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity
import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty
import org.grails.orm.hibernate.cfg.GrailsDomainBinder
import org.hibernate.mapping.ManyToOne
-import org.hibernate.mapping.OneToOne // Import OneToOne
import org.hibernate.mapping.Property
import org.hibernate.mapping.RootClass
import org.hibernate.mapping.SimpleValue
+import org.grails.orm.hibernate.cfg.PropertyConfig
+import org.grails.orm.hibernate.cfg.ColumnConfig
+import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder
+import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType
+import org.hibernate.boot.spi.InFlightMetadataCollector
+import org.hibernate.boot.spi.MetadataBuildingContext
+import org.hibernate.mapping.BasicValue
+import org.hibernate.mapping.Collection
+import org.hibernate.mapping.Component
+import org.hibernate.mapping.OneToOne
+import org.hibernate.mapping.PersistentClass
+import org.hibernate.mapping.Table
+import org.hibernate.mapping.Value
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+import java.util.Arrays
+import java.util.HashMap
+import java.util.Properties
+import java.util.Optional
+
+import static org.grails.orm.hibernate.cfg.GrailsDomainBinder.EMPTY_PATH
class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
@@ -35,7 +56,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def titleProp = persistentEntity.getPropertyByName("title") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", titleProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", titleProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, titleProp))
then:
Property prop = rootClass.getProperty("title")
@@ -56,7 +78,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def statusProp = persistentEntity.getPropertyByName("status") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", statusProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", statusProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, statusProp))
then:
Property prop = rootClass.getProperty("status")
@@ -81,7 +104,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def ownerProp = petEntity.getPropertyByName("owner") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", ownerProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", ownerProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, ownerProp))
then:
Property prop = rootClass.getProperty("owner")
@@ -103,7 +127,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def addressProp = persistentEntity.getPropertyByName("homeAddress") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", addressProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", addressProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, addressProp))
then:
Property prop = rootClass.getProperty("homeAddress")
@@ -130,7 +155,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def petsProp = personEntity.getPropertyByName("pets") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", petsProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", petsProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, petsProp))
then:
Property prop = rootClass.getProperty("pets")
@@ -168,7 +194,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def booksProp = authorEntity.getPropertyByName("books") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", booksProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", booksProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, booksProp))
collector.processSecondPasses(binder.getMetadataBuildingContext())
then:
@@ -206,7 +233,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def booksProp = authorEntity.getPropertyByName("books") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", booksProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", booksProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, booksProp))
collector.processSecondPasses(binder.getMetadataBuildingContext())
then:
@@ -266,7 +294,8 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
when:
def childBookProp = authorEntity.getPropertyByName("childBook") as GrailsHibernatePersistentProperty
- propertyBinder.bindProperty(rootClass, collector, "sessionFactory", childBookProp)
+ Value value = propertyBinder.bindProperty(rootClass, collector, "sessionFactory", childBookProp)
+ rootClass.addProperty(binder.getPropertyFromValueCreator().createProperty(value, childBookProp))
// Process second passes to ensure Hibernate's internal mappings are finalized
collector.processSecondPasses(binder.getMetadataBuildingContext())
@@ -287,12 +316,9 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
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 propertyFromValueCreator = Mock(PropertyFromValueCreator) // Mock propertyFromValueCreator as it is a constructor parameter
+ // Instantiate GrailsPropertyBinder using the protected constructor with necessary mocks
def propertyBinder = new GrailsPropertyBinder(
metadataBuildingContext,
namingStrategy,
@@ -300,11 +326,7 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
enumTypeBinder,
componentPropertyBinder,
collectionBinder,
- propertyFromValueCreator,
- simpleValueBinder,
- columnNameForPropertyAndPathFetcher,
- oneToOneBinder,
- manyToOneBinder
+ propertyFromValueCreator
)
def mappings = Mock(org.hibernate.boot.spi.InFlightMetadataCollector)
@@ -314,23 +336,41 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
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()
+ // Mocking currentGrailsProp and its dependencies to prevent NPEs
+ def mockOwner = Mock(org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity)
+ def mockMapping = new org.grails.orm.hibernate.cfg.Mapping()
+ mockMapping.setComment("test comment") // Provide a comment
+ currentGrailsProp.getHibernateOwner() >> mockOwner
+ mockOwner.getMappedForm() >> mockMapping // Return the Mapping object
+
+ // Stubbing getOwner() to return mockOwner
+ currentGrailsProp.getOwner() >> mockOwner
+ mockOwner.isRoot() >> true // Stub isRoot() to prevent NPE in ColumnBinder
+
+ // Mock PropertyConfig and stub its methods for SimpleValueBinder
+ def propertyConfigMock = Mock(PropertyConfig)
+ currentGrailsProp.getMappedForm() >> propertyConfigMock // For SimpleValueBinder logic, need PropertyConfig
+
+ propertyConfigMock.getGenerator() >> null
+ propertyConfigMock.getTypeParams() >> new Properties()
+ propertyConfigMock.isDerived() >> false
+ def columnConfigMock = Mock(ColumnConfig) // Mock ColumnConfig for getColumns()
+ columnConfigMock.getName() >> "test_column" // Provide a column name to prevent NPE
+ propertyConfigMock.getColumns() >> Arrays.asList(columnConfigMock)
+
+ // Mocking other necessary properties of currentGrailsProp
currentGrailsProp.getType() >> String.class
currentGrailsProp.getName() >> "title"
- propertyFromValueCreator.createProperty(_ as org.hibernate.mapping.Value, currentGrailsProp) >> new Property()
-
when:
- propertyBinder.bindProperty(rootClass, mappings, "sessionFactory", currentGrailsProp)
+ // Capture the return value of bindProperty
+ def resultValue = propertyBinder.bindProperty(rootClass, mappings, "sessionFactory", currentGrailsProp)
then:
- 1 * simpleValueBinder.bindSimpleValue(currentGrailsProp, null, _ as SimpleValue, "")
+ // Assert that bindProperty returns a Value object
+ resultValue instanceof Value
}
-
-
}