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 84500c9a2d405903059437010c33d99197930ef4
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Sun Feb 15 23:11:40 2026 -0600

    Merge ComponentPropertyBinder into ComponentBinder
    
    - Consolidate all component property binding logic into ComponentBinder.
    - Enable recursive component binding by having ComponentBinder call its own 
methods for embedded properties.
    - Remove redundant ComponentPropertyBinder and its associated test 
specification.
    - Update GrailsDomainBinder and CompositeIdBinder to use the consolidated 
ComponentBinder.
    - Migrate and update unit tests to ensure continued coverage of property 
binding logic within ComponentBinderSpec.
---
 .../orm/hibernate/cfg/GrailsDomainBinder.java      |   8 +-
 .../cfg/domainbinding/binder/ComponentBinder.java  | 104 +++++++-
 .../binder/ComponentPropertyBinder.java            | 124 ----------
 .../domainbinding/binder/CompositeIdBinder.java    |   8 +-
 .../cfg/domainbinding/CollectionBinderSpec.groovy  |   8 +-
 .../CollectionSecondPassBinderSpec.groovy          |   8 +-
 .../cfg/domainbinding/ComponentBinderSpec.groovy   | 251 +++++++++++++++++++-
 .../ComponentPropertyBinderSpec.groovy             | 263 ---------------------
 .../cfg/domainbinding/CompositeIdBinderSpec.groovy |  10 +-
 .../domainbinding/GrailsPropertyBinderSpec.groovy  |  12 +-
 .../domainbinding/ListSecondPassBinderSpec.groovy  |   8 +-
 .../domainbinding/MapSecondPassBinderSpec.groovy   |   8 +-
 12 files changed, 368 insertions(+), 444 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 332fbac39a..0b639d8e0a 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
@@ -18,7 +18,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ClassPropertiesBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnConfigToColumnBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder;
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder;
@@ -185,8 +184,9 @@ public class GrailsDomainBinder
                 simpleValueColumnFetcher
         );
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator);
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
+                getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinder,
                 collectionBinder,
@@ -196,8 +196,6 @@ public class GrailsDomainBinder
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         );
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, getMappingCacheHolder(), 
componentPropertyBinder);
-        componentPropertyBinder.setComponentBinder(componentBinder);
 
         GrailsPropertyBinder grailsPropertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
@@ -212,7 +210,7 @@ public class GrailsDomainBinder
                 manyToOneBinder,
                 propertyFromValueCreator
         );
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder);
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder);
         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 753c1066c5..818406b9f0 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
@@ -2,29 +2,67 @@ package org.grails.orm.hibernate.cfg.domainbinding.binder;
 
 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.ManyToOne;
+import org.hibernate.mapping.OneToOne;
 import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.SimpleValue;
 import org.hibernate.mapping.Table;
+import org.hibernate.mapping.Value;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.grails.datastore.mapping.model.config.GormProperties;
+import org.grails.datastore.mapping.model.types.Association;
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity;
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty;
 import org.grails.orm.hibernate.cfg.GrailsHibernateUtil;
 import org.grails.orm.hibernate.cfg.MappingCacheHolder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty;
+import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
+import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder;
+import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType;
+import 
org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher;
 
 import jakarta.annotation.Nonnull;
 
 public class ComponentBinder {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(ComponentBinder.class);
+
     private final MetadataBuildingContext metadataBuildingContext;
     private final MappingCacheHolder mappingCacheHolder;
-    private final ComponentPropertyBinder componentPropertyBinder;
+    private final CollectionHolder collectionHolder;
+    private final EnumTypeBinder enumTypeBinder;
+    private final CollectionBinder collectionBinder;
+    private final ManyToOneBinder manyToOneBinder;
+    private final OneToOneBinder oneToOneBinder;
+    private final ColumnNameForPropertyAndPathFetcher 
columnNameForPropertyAndPathFetcher;
+    private final SimpleValueBinder simpleValueBinder;
+    private final ComponentUpdater componentUpdater;
 
-    public ComponentBinder(MetadataBuildingContext metadataBuildingContext, 
MappingCacheHolder mappingCacheHolder, ComponentPropertyBinder 
componentPropertyBinder) {
+    public ComponentBinder(MetadataBuildingContext metadataBuildingContext,
+                           MappingCacheHolder mappingCacheHolder,
+                           CollectionHolder collectionHolder,
+                           EnumTypeBinder enumTypeBinder,
+                           CollectionBinder collectionBinder,
+                           SimpleValueBinder simpleValueBinder,
+                           OneToOneBinder oneToOneBinder,
+                           ManyToOneBinder manyToOneBinder,
+                           ColumnNameForPropertyAndPathFetcher 
columnNameForPropertyAndPathFetcher,
+                           ComponentUpdater componentUpdater) {
         this.metadataBuildingContext = metadataBuildingContext;
         this.mappingCacheHolder = mappingCacheHolder;
-        this.componentPropertyBinder = componentPropertyBinder;
+        this.collectionHolder = collectionHolder;
+        this.enumTypeBinder = enumTypeBinder;
+        this.collectionBinder = collectionBinder;
+        this.simpleValueBinder = simpleValueBinder;
+        this.oneToOneBinder = oneToOneBinder;
+        this.manyToOneBinder = manyToOneBinder;
+        this.columnNameForPropertyAndPathFetcher = 
columnNameForPropertyAndPathFetcher;
+        this.componentUpdater = componentUpdater;
     }
 
 
@@ -52,9 +90,67 @@ public class ComponentBinder {
                 component.setParentProperty(currentGrailsProp.getName());
                 continue;
             }
-            componentPropertyBinder.bindComponentProperty(component, property, 
currentGrailsProp, persistentClass, path, table, mappings);
+            bindComponentProperty(component, property, currentGrailsProp, 
persistentClass, path, table, mappings);
 
         }
         return component;
     }
+
+    public Value bindComponentProperty(Component component,
+                                       GrailsHibernatePersistentProperty 
componentProperty,
+                                       GrailsHibernatePersistentProperty 
currentGrailsProp,
+                                       PersistentClass persistentClass,
+                                       String path,
+                                       Table table,
+                                       @Nonnull InFlightMetadataCollector 
mappings) {
+        Value value;
+        // see if it's a collection type
+        CollectionType collectionType = 
collectionHolder.get(currentGrailsProp.getType());
+        if (collectionType != null) {
+            // create collection
+            Collection collection = 
collectionType.create((HibernateToManyProperty) currentGrailsProp, 
persistentClass);
+            collectionBinder.bindCollection((HibernateToManyProperty) 
currentGrailsProp, collection, persistentClass, mappings, path);
+            mappings.addCollectionBinding(collection);
+            value = collection;
+        }
+        // work out what type of relationship it is and bind value
+        else if (currentGrailsProp instanceof 
org.grails.datastore.mapping.model.types.ManyToOne) {
+            if (LOG.isDebugEnabled())
+                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as ManyToOne");
+
+            value = new ManyToOne(metadataBuildingContext, table);
+            manyToOneBinder.bindManyToOne((Association) currentGrailsProp, 
(ManyToOne) value, path);
+        } else if (currentGrailsProp instanceof 
org.grails.datastore.mapping.model.types.OneToOne association) {
+            if (LOG.isDebugEnabled())
+                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as OneToOne");
+
+            if (association.canBindOneToOneWithSingleColumnAndForeignKey()) {
+                value = new OneToOne(metadataBuildingContext, table, 
persistentClass);
+                
oneToOneBinder.bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne) 
currentGrailsProp, (OneToOne) value, path);
+            }
+            else {
+                value = new ManyToOne(metadataBuildingContext, table);
+                manyToOneBinder.bindManyToOne((Association) currentGrailsProp, 
(ManyToOne) value, path);
+            }
+        }
+        else if (currentGrailsProp instanceof HibernateEmbeddedProperty 
embedded) {
+            value = bindComponent(persistentClass, embedded, mappings);
+        }
+        else {
+            if (LOG.isDebugEnabled())
+                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as SimpleValue");
+
+            value = new BasicValue(metadataBuildingContext, table);
+            if (currentGrailsProp.getType().isEnum()) {
+                String columnName = 
columnNameForPropertyAndPathFetcher.getColumnNameForPropertyAndPath(currentGrailsProp,
 path, null);
+                enumTypeBinder.bindEnumType(currentGrailsProp, 
currentGrailsProp.getType(), (SimpleValue) value, columnName);
+            }
+            else {
+                // set type
+                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/ComponentPropertyBinder.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentPropertyBinder.java
deleted file mode 100644
index 52f8222271..0000000000
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentPropertyBinder.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package org.grails.orm.hibernate.cfg.domainbinding.binder;
-
-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.ManyToOne;
-import org.hibernate.mapping.OneToOne;
-import org.hibernate.mapping.PersistentClass;
-import org.hibernate.mapping.SimpleValue;
-import org.hibernate.mapping.Table;
-import org.hibernate.mapping.Value;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.grails.datastore.mapping.model.types.Association;
-import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty;
-import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty;
-import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
-import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder;
-import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType;
-import 
org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher;
-
-import jakarta.annotation.Nonnull;
-
-public class ComponentPropertyBinder {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(ComponentPropertyBinder.class);
-
-    private final MetadataBuildingContext metadataBuildingContext;
-    private final CollectionHolder collectionHolder;
-    private final EnumTypeBinder enumTypeBinder;
-    private final CollectionBinder collectionBinder;
-    private final ManyToOneBinder manyToOneBinder;
-    private final OneToOneBinder oneToOneBinder;
-    private final ColumnNameForPropertyAndPathFetcher 
columnNameForPropertyAndPathFetcher;
-    private final SimpleValueBinder simpleValueBinder;
-    private final ComponentUpdater componentUpdater;
-    private ComponentBinder componentBinder;
-
-    public ComponentPropertyBinder(MetadataBuildingContext 
metadataBuildingContext,
-                                      CollectionHolder collectionHolder,
-                                      EnumTypeBinder enumTypeBinder,
-                                      CollectionBinder collectionBinder,
-                                      SimpleValueBinder simpleValueBinder,
-                                      OneToOneBinder oneToOneBinder,
-                                      ManyToOneBinder manyToOneBinder,
-                                      ColumnNameForPropertyAndPathFetcher 
columnNameForPropertyAndPathFetcher,
-                                      ComponentUpdater componentUpdater) {
-        this.metadataBuildingContext = metadataBuildingContext;
-        this.collectionHolder = collectionHolder;
-        this.enumTypeBinder = enumTypeBinder;
-        this.collectionBinder = collectionBinder;
-        this.simpleValueBinder = simpleValueBinder;
-        this.oneToOneBinder = oneToOneBinder;
-        this.manyToOneBinder = manyToOneBinder;
-        this.columnNameForPropertyAndPathFetcher = 
columnNameForPropertyAndPathFetcher;
-        this.componentUpdater = componentUpdater;
-    }
-
-    public void setComponentBinder(ComponentBinder componentBinder) {
-        this.componentBinder = componentBinder;
-    }
-
-    public Value bindComponentProperty(Component component,
-                                       GrailsHibernatePersistentProperty 
componentProperty,
-                                       GrailsHibernatePersistentProperty 
currentGrailsProp,
-                                       PersistentClass persistentClass,
-                                       String path,
-                                       Table table,
-                                       @Nonnull InFlightMetadataCollector 
mappings) {
-        Value value;
-        // see if it's a collection type
-        CollectionType collectionType = 
collectionHolder.get(currentGrailsProp.getType());
-        if (collectionType != null) {
-            // create collection
-            Collection collection = 
collectionType.create((HibernateToManyProperty) currentGrailsProp, 
persistentClass);
-            collectionBinder.bindCollection((HibernateToManyProperty) 
currentGrailsProp, collection, persistentClass, mappings, path);
-            mappings.addCollectionBinding(collection);
-            value = collection;
-        }
-        // work out what type of relationship it is and bind value
-        else if (currentGrailsProp instanceof 
org.grails.datastore.mapping.model.types.ManyToOne) {
-            if (LOG.isDebugEnabled())
-                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as ManyToOne");
-
-            value = new ManyToOne(metadataBuildingContext, table);
-            manyToOneBinder.bindManyToOne((Association) currentGrailsProp, 
(ManyToOne) value, path);
-        } else if (currentGrailsProp instanceof 
org.grails.datastore.mapping.model.types.OneToOne association) {
-            if (LOG.isDebugEnabled())
-                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as OneToOne");
-
-            if (association.canBindOneToOneWithSingleColumnAndForeignKey()) {
-                value = new OneToOne(metadataBuildingContext, table, 
persistentClass);
-                
oneToOneBinder.bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne) 
currentGrailsProp, (OneToOne) value, path);
-            }
-            else {
-                value = new ManyToOne(metadataBuildingContext, table);
-                manyToOneBinder.bindManyToOne((Association) currentGrailsProp, 
(ManyToOne) value, path);
-            }
-        }
-        else if (currentGrailsProp instanceof HibernateEmbeddedProperty 
embedded) {
-            value = componentBinder.bindComponent(persistentClass, embedded, 
mappings);
-        }
-        else {
-            if (LOG.isDebugEnabled())
-                LOG.debug("[GrailsDomainBinder] Binding property [" + 
currentGrailsProp.getName() + "] as SimpleValue");
-
-            value = new BasicValue(metadataBuildingContext, table);
-            if (currentGrailsProp.getType().isEnum()) {
-                String columnName = 
columnNameForPropertyAndPathFetcher.getColumnNameForPropertyAndPath(currentGrailsProp,
 path, null);
-                enumTypeBinder.bindEnumType(currentGrailsProp, 
currentGrailsProp.getType(), (SimpleValue) value, columnName);
-            }
-            else {
-                // set type
-                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 3dd7d6ae32..90b4e415fb 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
@@ -16,11 +16,11 @@ import jakarta.annotation.Nonnull;
 public class CompositeIdBinder {
 
     private final MetadataBuildingContext metadataBuildingContext;
-    private final ComponentPropertyBinder componentPropertyBinder;
+    private final ComponentBinder componentBinder;
 
-    public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, 
ComponentPropertyBinder componentPropertyBinder) {
+    public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, 
ComponentBinder componentBinder) {
         this.metadataBuildingContext = metadataBuildingContext;
-        this.componentPropertyBinder = componentPropertyBinder;
+        this.componentBinder = componentBinder;
     }
 
 
@@ -61,7 +61,7 @@ public class CompositeIdBinder {
                         "] is not a valid property!");
             }
 
-           componentPropertyBinder.bindComponentProperty(id, identifierProp, 
property, root, "", root.getTable(), mappings);
+           componentBinder.bindComponentProperty(id, identifierProp, property, 
root, "", root.getTable(), mappings);
         }
     }
 }
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy
index c0628bbae4..455690daf3 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy
@@ -35,7 +35,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndP
 import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder
 import org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
 import org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator
 
@@ -81,8 +80,9 @@ class CollectionBinderSpec extends HibernateGormDatastoreSpec 
{
         )
         PropertyFromValueCreator propertyFromValueCreator = new 
PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator)
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
+                binder.getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinderToUse,
                 collectionBinder,
@@ -92,8 +92,6 @@ class CollectionBinderSpec extends HibernateGormDatastoreSpec 
{
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         )
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, binder.getMappingCacheHolder(), 
componentPropertyBinder)
-        componentPropertyBinder.setComponentBinder(componentBinder)
 
         GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
@@ -108,7 +106,7 @@ class CollectionBinderSpec extends 
HibernateGormDatastoreSpec {
                 manyToOneBinder,
                 propertyFromValueCreator
         )
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder)
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder)
         PropertyBinder propertyBinderHelper = new PropertyBinder()
         SimpleIdBinder simpleIdBinder = new 
SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new 
BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, 
compositeIdBinder)
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy
index 90d81ffcab..d58eed4f01 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy
@@ -20,7 +20,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
 import org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator
 import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder
@@ -80,8 +79,9 @@ class CollectionSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
         )
         PropertyFromValueCreator propertyFromValueCreator = new 
PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator)
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
+                binder.getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinderToUse,
                 collectionBinder,
@@ -91,8 +91,6 @@ class CollectionSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         )
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, binder.getMappingCacheHolder(), 
componentPropertyBinder)
-        componentPropertyBinder.setComponentBinder(componentBinder)
 
         GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
@@ -107,7 +105,7 @@ class CollectionSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 manyToOneBinder,
                 propertyFromValueCreator
         )
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder)
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder)
         PropertyBinder propertyBinderHelper = new PropertyBinder()
         SimpleIdBinder simpleIdBinder = new 
SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new 
BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, 
compositeIdBinder)
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 6bee48a1f6..619364cebf 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
@@ -1,30 +1,95 @@
 package org.grails.orm.hibernate.cfg.domainbinding
 
 import grails.gorm.specs.HibernateGormDatastoreSpec
-import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty
-import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty
+import org.grails.datastore.mapping.model.MappingContext
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.grails.datastore.mapping.model.PersistentProperty
+import org.grails.datastore.mapping.model.types.Association
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity
+import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty
+import org.grails.orm.hibernate.cfg.Mapping
 import org.grails.orm.hibernate.cfg.MappingCacheHolder
-
+import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy
+import org.grails.orm.hibernate.cfg.PropertyConfig
+import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty
+import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty
+import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToOneProperty
+import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
+import org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder
+import 
org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher
+import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder
+import org.hibernate.boot.spi.InFlightMetadataCollector
+import org.hibernate.mapping.BasicValue
 import org.hibernate.mapping.Component
+import org.hibernate.mapping.ManyToOne as HibernateManyToOne
+import org.hibernate.mapping.OneToOne as HibernateOneToOne
+import org.hibernate.mapping.Property
 import org.hibernate.mapping.RootClass
+import org.hibernate.mapping.Table
+import org.hibernate.mapping.Value
 import spock.lang.Subject
 
-import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
-import org.hibernate.mapping.Value
-import org.hibernate.mapping.Table
+import org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator
 
 class ComponentBinderSpec extends HibernateGormDatastoreSpec {
 
+    abstract static class TestManyToOne extends HibernateManyToOneProperty {
+        TestManyToOne(PersistentEntity owner, MappingContext context, 
java.beans.PropertyDescriptor descriptor) {
+            super(owner, context, descriptor);
+        }
+    }
+
+    abstract static class TestOneToOne extends HibernateOneToOneProperty {
+        TestOneToOne(PersistentEntity owner, MappingContext context, 
java.beans.PropertyDescriptor descriptor) {
+            super(owner, context, descriptor);
+        }
+    }
+
     MappingCacheHolder mappingCacheHolder = Mock(MappingCacheHolder)
-    ComponentPropertyBinder componentPropertyBinder = 
Mock(ComponentPropertyBinder)
+    CollectionHolder collectionHolder = new CollectionHolder([:])
+    EnumTypeBinder enumTypeBinder = Mock(EnumTypeBinder)
+    CollectionBinder collectionBinder = Mock(CollectionBinder)
+    PropertyFromValueCreator propertyFromValueCreator = 
Mock(PropertyFromValueCreator)
+    OneToOneBinder oneToOneBinder = Mock(OneToOneBinder)
+    ManyToOneBinder manyToOneBinder = Mock(ManyToOneBinder)
+    ColumnNameForPropertyAndPathFetcher columnNameFetcher = 
Mock(ColumnNameForPropertyAndPathFetcher)
+    ComponentUpdater componentUpdater
+    SimpleValueBinder mockSimpleValueBinder = Mock(SimpleValueBinder)
 
     @Subject
     ComponentBinder binder
 
     def setup() {
-        binder = new 
ComponentBinder(getGrailsDomainBinder().getMetadataBuildingContext(), 
mappingCacheHolder, componentPropertyBinder)
+        componentUpdater = new ComponentUpdater(propertyFromValueCreator)
+        
+        binder = new ComponentBinder(
+                getGrailsDomainBinder().getMetadataBuildingContext(),
+                mappingCacheHolder,
+                collectionHolder,
+                enumTypeBinder,
+                collectionBinder,
+                mockSimpleValueBinder,
+                oneToOneBinder,
+                manyToOneBinder,
+                columnNameFetcher,
+                componentUpdater
+        )
+    }
+
+    private void setupProperty(PersistentProperty prop, String name, Mapping 
mapping, PersistentEntity owner) {
+        prop.getName() >> name
+        _ * prop.getOwner() >> owner
+        if (prop instanceof GrailsHibernatePersistentProperty) {
+            _ * ((GrailsHibernatePersistentProperty)prop).getHibernateOwner() 
>> owner
+        }
+        def config = new PropertyConfig()
+        mapping.getColumns().put(name, config)
+        prop.getMappedForm() >> config
     }
 
     def "should bind component and its properties"() {
@@ -60,9 +125,175 @@ class ComponentBinderSpec extends 
HibernateGormDatastoreSpec {
         component.getComponentClassName() == Address.name
         component.getRoleName() == Address.name + ".address"
         1 * mappingCacheHolder.cacheMapping(associatedEntity)
-        1 * componentPropertyBinder.bindComponentProperty(_ as Component, 
embeddedProp, prop1, root, "address", _ as Table, mappings) >> Mock(Value)
+        1 * mockSimpleValueBinder.bindSimpleValue(prop1, embeddedProp, _ as 
BasicValue, "address")
+    }
+
+    def "should bind simple property"() {
+        given:
+        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
+        def root = new RootClass(metadataBuildingContext)
+        def component = new Component(metadataBuildingContext, root)
+        def table = new Table("my_table")
+        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
+        ownerEntity.isRoot() >> true
+
+        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
+        
+        def componentProperty = Mock(GrailsHibernatePersistentProperty)
+        def mappings = Mock(InFlightMetadataCollector)
+        def hibernateProperty = new Property()
+        hibernateProperty.setName("street")
+        
+        def mapping = new Mapping()
+        ownerEntity.getMappedForm() >> mapping
+        currentGrailsProp.getType() >> String
+        setupProperty(currentGrailsProp, "street", mapping, ownerEntity)
+        setupProperty(componentProperty, "address", mapping, ownerEntity)
+        
+        when:
+        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
+
+        then:
+        1 * mockSimpleValueBinder.bindSimpleValue(currentGrailsProp, 
componentProperty, _ as BasicValue, "address")
+        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
+    }
+
+    def "should bind many-to-one property"() {
+        given:
+        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
+        def root = new RootClass(metadataBuildingContext)
+        def component = new Component(metadataBuildingContext, root)
+        def table = new Table("my_table")
+        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
+        ownerEntity.isRoot() >> true
+        def currentGrailsProp = Mock(TestManyToOne)
+        def componentProperty = Mock(GrailsHibernatePersistentProperty)
+        def mappings = Mock(InFlightMetadataCollector)
+        def hibernateProperty = new Property()
+        hibernateProperty.setName("owner")
+
+        def mapping = new Mapping()
+        ownerEntity.getMappedForm() >> mapping
+        currentGrailsProp.getAssociatedEntity() >> 
Mock(GrailsHibernatePersistentEntity) { 
+            getName() >> "Owner" 
+            getMappedForm() >> new Mapping()
+            isRoot() >> true
+        }
+        currentGrailsProp.getType() >> Object
+        setupProperty(currentGrailsProp, "owner", mapping, ownerEntity)
+        setupProperty(componentProperty, "address", mapping, ownerEntity)
+        
+        when:
+        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
+
+        then:
+        1 * manyToOneBinder.bindManyToOne(currentGrailsProp, _ as 
HibernateManyToOne, "address")
+        1 * propertyFromValueCreator.createProperty(_ as HibernateManyToOne, 
currentGrailsProp) >> hibernateProperty
+    }
+
+    def "should bind one-to-one property"() {
+        given:
+        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
+        def root = new RootClass(metadataBuildingContext)
+        def component = new Component(metadataBuildingContext, root)
+        def table = new Table("my_table")
+        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
+        ownerEntity.isRoot() >> true
+        def currentGrailsProp = Mock(TestOneToOne)
+        def componentProperty = Mock(GrailsHibernatePersistentProperty)
+        def mappings = Mock(InFlightMetadataCollector)
+        def hibernateProperty = new Property()
+        hibernateProperty.setName("detail")
+
+        def mapping = new Mapping()
+        ownerEntity.getMappedForm() >> mapping
+        ((Association)currentGrailsProp).getInverseSide() >> Mock(Association) 
{
+            isHasOne() >> false
+            getOwner() >> Mock(GrailsHibernatePersistentEntity) { 
+                getName() >> "Other" 
+                isRoot() >> true
+            }
+            getName() >> "other"
+        }
+        currentGrailsProp.getType() >> Object
+        
((Association)currentGrailsProp).canBindOneToOneWithSingleColumnAndForeignKey() 
>> true
+        setupProperty(currentGrailsProp, "detail", mapping, ownerEntity)
+        setupProperty(componentProperty, "address", mapping, ownerEntity)
+        
+        when:
+        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
+
+        then:
+        1 * oneToOneBinder.bindOneToOne(currentGrailsProp, _ as 
HibernateOneToOne, "address")
+        1 * propertyFromValueCreator.createProperty(_ as HibernateOneToOne, 
currentGrailsProp) >> hibernateProperty
+    }
+
+    def "should bind enum property"() {
+        given:
+        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
+        def root = new RootClass(metadataBuildingContext)
+        def component = new Component(metadataBuildingContext, root)
+        def table = new Table("my_table")
+        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
+        ownerEntity.isRoot() >> true
+        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
+        def componentProperty = Mock(GrailsHibernatePersistentProperty)
+        def mappings = Mock(InFlightMetadataCollector)
+        def hibernateProperty = new Property()
+        hibernateProperty.setName("type")
+
+        def mapping = new Mapping()
+        ownerEntity.getMappedForm() >> mapping
+        currentGrailsProp.getType() >> MyEnum
+        setupProperty(currentGrailsProp, "type", mapping, ownerEntity)
+        setupProperty(componentProperty, "address", mapping, ownerEntity)
+        
+        columnNameFetcher.getColumnNameForPropertyAndPath(currentGrailsProp, 
"address", null) >> "address_type_col"
+
+        when:
+        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
+
+        then:
+        1 * enumTypeBinder.bindEnumType(currentGrailsProp, MyEnum, _ as 
BasicValue, "address_type_col")
+        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
+    }
+
+    def "should set columns to nullable when component property is nullable"() 
{
+        given:
+        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
+        def root = new RootClass(metadataBuildingContext)
+        def component = new Component(metadataBuildingContext, root)
+        def table = new Table("my_table")
+        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
+        ownerEntity.isRoot() >> true
+        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
+        def componentProperty = Mock(GrailsHibernatePersistentProperty)
+        def mappings = Mock(InFlightMetadataCollector)
+        def hibernateProperty = new Property()
+        hibernateProperty.setName("street")
+        
+        def mapping = new Mapping()
+        ownerEntity.getMappedForm() >> mapping
+        currentGrailsProp.getType() >> String
+        setupProperty(currentGrailsProp, "street", mapping, ownerEntity)
+        setupProperty(componentProperty, "address", mapping, ownerEntity)
+        
+        ownerEntity.isComponentPropertyNullable(componentProperty) >> true
+        
+        when:
+        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
+
+        then:
+        1 * mockSimpleValueBinder.bindSimpleValue(
+            currentGrailsProp, 
+            componentProperty, 
+            _ as BasicValue, 
+            "address"
+        )
+        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
     }
 
     static class MyEntity {}
     static class Address {}
+    enum MyEnum { VAL }
 }
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentPropertyBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentPropertyBinderSpec.groovy
deleted file mode 100644
index 87e522ad36..0000000000
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentPropertyBinderSpec.groovy
+++ /dev/null
@@ -1,263 +0,0 @@
-package org.grails.orm.hibernate.cfg.domainbinding
-
-import grails.gorm.specs.HibernateGormDatastoreSpec
-import org.grails.datastore.mapping.model.MappingContext
-import org.grails.datastore.mapping.model.PersistentEntity
-import org.grails.datastore.mapping.model.PersistentProperty
-import org.grails.datastore.mapping.model.types.Association
-import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity
-import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty
-import org.grails.orm.hibernate.cfg.Mapping
-import org.grails.orm.hibernate.cfg.MappingCacheHolder
-import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy
-import org.grails.orm.hibernate.cfg.PropertyConfig
-import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty
-import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToOneProperty
-import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
-import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
-import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
-import org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder
-import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder
-import org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder
-import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher
-import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder
-import org.hibernate.boot.spi.InFlightMetadataCollector
-import org.hibernate.mapping.BasicValue
-import org.hibernate.mapping.Component
-import org.hibernate.mapping.ManyToOne as HibernateManyToOne
-import org.hibernate.mapping.OneToOne as HibernateOneToOne
-import org.hibernate.mapping.Property
-import org.hibernate.mapping.RootClass
-import org.hibernate.mapping.Table
-import spock.lang.Subject
-
-import org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator
-
-class ComponentPropertyBinderSpec extends HibernateGormDatastoreSpec {
-
-    abstract static class TestManyToOne extends HibernateManyToOneProperty {
-        TestManyToOne(PersistentEntity owner, MappingContext context, 
java.beans.PropertyDescriptor descriptor) {
-            super(owner, context, descriptor);
-        }
-    }
-
-    abstract static class TestOneToOne extends HibernateOneToOneProperty {
-        TestOneToOne(PersistentEntity owner, MappingContext context, 
java.beans.PropertyDescriptor descriptor) {
-            super(owner, context, descriptor);
-        }
-    }
-
-    PersistentEntityNamingStrategy namingStrategy = 
Mock(PersistentEntityNamingStrategy)
-    MappingCacheHolder mappingCacheHolder = Mock(MappingCacheHolder)
-    CollectionHolder collectionHolder = new CollectionHolder([:])
-    EnumTypeBinder enumTypeBinder = Mock(EnumTypeBinder)
-    CollectionBinder collectionBinder = Mock(CollectionBinder)
-    PropertyFromValueCreator propertyFromValueCreator = 
Mock(PropertyFromValueCreator)
-    ComponentBinder componentBinder = Mock(ComponentBinder)
-    OneToOneBinder oneToOneBinder = Mock(OneToOneBinder)
-    ManyToOneBinder manyToOneBinder = Mock(ManyToOneBinder)
-    ColumnNameForPropertyAndPathFetcher columnNameFetcher = 
Mock(ColumnNameForPropertyAndPathFetcher)
-    ComponentUpdater componentUpdater
-
-    @Subject
-    ComponentPropertyBinder binder
-
-    def mockSimpleValueBinder = Mock(SimpleValueBinder) // Mock 
SimpleValueBinder
-
-    def setup() {
-        componentUpdater = new ComponentUpdater(propertyFromValueCreator)
-        
-        binder = new ComponentPropertyBinder(
-                getGrailsDomainBinder().getMetadataBuildingContext(),
-                collectionHolder,
-                enumTypeBinder,
-                collectionBinder,
-                mockSimpleValueBinder,
-                oneToOneBinder,
-                manyToOneBinder,
-                columnNameFetcher,
-                componentUpdater
-        )
-        binder.setComponentBinder(componentBinder)
-    }
-
-    private void setupProperty(PersistentProperty prop, String name, Mapping 
mapping, PersistentEntity owner) {
-        prop.getName() >> name
-        _ * prop.getOwner() >> owner
-        if (prop instanceof GrailsHibernatePersistentProperty) {
-            _ * ((GrailsHibernatePersistentProperty)prop).getHibernateOwner() 
>> owner
-        }
-        def config = new PropertyConfig()
-        mapping.getColumns().put(name, config)
-        prop.getMappedForm() >> config
-    }
-
-    def "should bind simple property"() {
-        given:
-        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
-        def root = new RootClass(metadataBuildingContext)
-        def component = new Component(metadataBuildingContext, root)
-        def table = new Table("my_table")
-        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
-        ownerEntity.isRoot() >> true
-
-        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
-        
-        def componentProperty = Mock(GrailsHibernatePersistentProperty)
-        def mappings = Mock(InFlightMetadataCollector)
-        def hibernateProperty = new Property()
-        hibernateProperty.setName("street")
-        
-        def mapping = new Mapping()
-        ownerEntity.getMappedForm() >> mapping
-        currentGrailsProp.getType() >> String
-        setupProperty(currentGrailsProp, "street", mapping, ownerEntity)
-        setupProperty(componentProperty, "address", mapping, ownerEntity)
-        
-        when:
-        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
-
-        then:
-        1 * mockSimpleValueBinder.bindSimpleValue(currentGrailsProp, 
componentProperty, _ as BasicValue, "address")
-        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
-    }
-
-    def "should bind many-to-one property"() {
-        given:
-        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
-        def root = new RootClass(metadataBuildingContext)
-        def component = new Component(metadataBuildingContext, root)
-        def table = new Table("my_table")
-        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
-        ownerEntity.isRoot() >> true
-        def currentGrailsProp = Mock(TestManyToOne)
-        def componentProperty = Mock(GrailsHibernatePersistentProperty)
-        def mappings = Mock(InFlightMetadataCollector)
-        def hibernateProperty = new Property()
-        hibernateProperty.setName("owner")
-
-        def mapping = new Mapping()
-        ownerEntity.getMappedForm() >> mapping
-        currentGrailsProp.getAssociatedEntity() >> 
Mock(GrailsHibernatePersistentEntity) { 
-            getName() >> "Owner" 
-            getMappedForm() >> new Mapping()
-            isRoot() >> true
-        }
-        currentGrailsProp.getType() >> Object
-        setupProperty(currentGrailsProp, "owner", mapping, ownerEntity)
-        setupProperty(componentProperty, "address", mapping, ownerEntity)
-        
-        when:
-        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
-
-        then:
-        1 * manyToOneBinder.bindManyToOne(currentGrailsProp, _ as 
HibernateManyToOne, "address")
-        1 * propertyFromValueCreator.createProperty(_ as HibernateManyToOne, 
currentGrailsProp) >> hibernateProperty
-    }
-
-    def "should bind one-to-one property"() {
-        given:
-        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
-        def root = new RootClass(metadataBuildingContext)
-        def component = new Component(metadataBuildingContext, root)
-        def table = new Table("my_table")
-        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
-        ownerEntity.isRoot() >> true
-        def currentGrailsProp = Mock(TestOneToOne)
-        def componentProperty = Mock(GrailsHibernatePersistentProperty)
-        def mappings = Mock(InFlightMetadataCollector)
-        def hibernateProperty = new Property()
-        hibernateProperty.setName("detail")
-
-        def mapping = new Mapping()
-        ownerEntity.getMappedForm() >> mapping
-        ((Association)currentGrailsProp).getInverseSide() >> Mock(Association) 
{
-            isHasOne() >> false
-            getOwner() >> Mock(GrailsHibernatePersistentEntity) { 
-                getName() >> "Other" 
-                isRoot() >> true
-            }
-            getName() >> "other"
-        }
-        currentGrailsProp.getType() >> Object
-        
((Association)currentGrailsProp).canBindOneToOneWithSingleColumnAndForeignKey() 
>> true
-        setupProperty(currentGrailsProp, "detail", mapping, ownerEntity)
-        setupProperty(componentProperty, "address", mapping, ownerEntity)
-        
-        when:
-        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
-
-        then:
-        1 * oneToOneBinder.bindOneToOne(currentGrailsProp, _ as 
HibernateOneToOne, "address")
-        1 * propertyFromValueCreator.createProperty(_ as HibernateOneToOne, 
currentGrailsProp) >> hibernateProperty
-    }
-
-    def "should bind enum property"() {
-        given:
-        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
-        def root = new RootClass(metadataBuildingContext)
-        def component = new Component(metadataBuildingContext, root)
-        def table = new Table("my_table")
-        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
-        ownerEntity.isRoot() >> true
-        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
-        def componentProperty = Mock(GrailsHibernatePersistentProperty)
-        def mappings = Mock(InFlightMetadataCollector)
-        def hibernateProperty = new Property()
-        hibernateProperty.setName("type")
-
-        def mapping = new Mapping()
-        ownerEntity.getMappedForm() >> mapping
-        currentGrailsProp.getType() >> MyEnum
-        setupProperty(currentGrailsProp, "type", mapping, ownerEntity)
-        setupProperty(componentProperty, "address", mapping, ownerEntity)
-        
-        columnNameFetcher.getColumnNameForPropertyAndPath(currentGrailsProp, 
"address", null) >> "address_type_col"
-
-        when:
-        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
-
-        then:
-        1 * enumTypeBinder.bindEnumType(currentGrailsProp, MyEnum, _ as 
BasicValue, "address_type_col")
-        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
-    }
-
-    def "should set columns to nullable when component property is nullable"() 
{
-        given:
-        def metadataBuildingContext = 
getGrailsDomainBinder().getMetadataBuildingContext()
-        def root = new RootClass(metadataBuildingContext)
-        def component = new Component(metadataBuildingContext, root)
-        def table = new Table("my_table")
-        def ownerEntity = Mock(GrailsHibernatePersistentEntity)
-        ownerEntity.isRoot() >> true
-        def currentGrailsProp = Mock(GrailsHibernatePersistentProperty)
-        def componentProperty = Mock(GrailsHibernatePersistentProperty)
-        def mappings = Mock(InFlightMetadataCollector)
-        def hibernateProperty = new Property()
-        hibernateProperty.setName("street")
-        
-        def mapping = new Mapping()
-        ownerEntity.getMappedForm() >> mapping
-        currentGrailsProp.getType() >> String
-        setupProperty(currentGrailsProp, "street", mapping, ownerEntity)
-        setupProperty(componentProperty, "address", mapping, ownerEntity)
-        
-        ownerEntity.isComponentPropertyNullable(componentProperty) >> true
-        
-        when:
-        binder.bindComponentProperty(component, componentProperty, 
currentGrailsProp, root, "address", table, mappings)
-
-        then:
-        1 * mockSimpleValueBinder.bindSimpleValue(
-            currentGrailsProp, 
-            componentProperty, 
-            _ as BasicValue, 
-            "address"
-        )
-        1 * propertyFromValueCreator.createProperty(_ as BasicValue, 
currentGrailsProp) >> hibernateProperty
-    }
-
-    enum MyEnum { VAL }
-}
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 1257776f72..15b580db45 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
@@ -11,19 +11,19 @@ import org.hibernate.mapping.RootClass
 import org.hibernate.mapping.Table
 import spock.lang.Subject
 
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder
 import org.hibernate.mapping.Value
 
 class CompositeIdBinderSpec extends HibernateGormDatastoreSpec {
 
-    def componentPropertyBinder = Mock(ComponentPropertyBinder)
+    def componentBinder = Mock(ComponentBinder)
 
     @Subject
     CompositeIdBinder binder
 
     def setup() {
-        binder = new 
CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), 
componentPropertyBinder)
+        binder = new 
CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), 
componentBinder)
     }
 
     def "should bind composite id using property names from 
CompositeIdentity"() {
@@ -54,7 +54,7 @@ class CompositeIdBinderSpec extends 
HibernateGormDatastoreSpec {
         root.getIdentifier() instanceof Component
         root.getIdentifierMapper() instanceof Component
         root.hasEmbeddedIdentifier()
-        2 * componentPropertyBinder.bindComponentProperty(_ as Component, 
identifierProp, _ as PersistentProperty, root, "", table, mappings) >> 
Mock(Value)
+        2 * componentBinder.bindComponentProperty(_ as Component, 
identifierProp, _ as PersistentProperty, root, "", table, mappings) >> 
Mock(Value)
     }
 
     def "should fallback to domainClass composite identity when 
CompositeIdentity is null"() {
@@ -78,7 +78,7 @@ class CompositeIdBinderSpec extends 
HibernateGormDatastoreSpec {
         binder.bindCompositeId(domainClass, root, null, mappings)
 
         then:
-        1 * componentPropertyBinder.bindComponentProperty(_ as Component, 
identifierProp, prop1, root, "", table, mappings) >> Mock(Value)
+        1 * componentBinder.bindComponentProperty(_ as Component, 
identifierProp, prop1, root, "", table, mappings) >> Mock(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 12933320f6..d672fe8e80 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
@@ -14,7 +14,6 @@ import org.hibernate.mapping.Value
 import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
 import org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder
@@ -85,23 +84,18 @@ class GrailsPropertyBinderSpec extends 
HibernateGormDatastoreSpec {
         )
         PropertyFromValueCreator propertyFromValueCreator = new 
PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator)
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
-                namingStrategy,
-                jdbcEnvironment,
                 binder.getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinderToUse,
                 collectionBinder,
-                propertyFromValueCreator,
-                null,
                 simpleValueBinder,
                 oneToOneBinder,
                 manyToOneBinder,
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         )
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, binder.getMappingCacheHolder(), 
componentPropertyBinder, componentUpdater)
         GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
                 namingStrategy,
@@ -115,7 +109,7 @@ class GrailsPropertyBinderSpec extends 
HibernateGormDatastoreSpec {
                 manyToOneBinder,
                 propertyFromValueCreator
         )
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder, 
componentUpdater)
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder)
         PropertyBinder propertyBinderHelper = new PropertyBinder()
         SimpleIdBinder simpleIdBinder = new 
SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new 
BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, 
compositeIdBinder)
@@ -550,4 +544,4 @@ class MapAuthor {
 class MapBook {
     Long id
     String title
-}
\ No newline at end of file
+}
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ListSecondPassBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ListSecondPassBinderSpec.groovy
index 33afb724f2..30ab28c01a 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ListSecondPassBinderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ListSecondPassBinderSpec.groovy
@@ -20,7 +20,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
 import org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator
 import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder
@@ -80,8 +79,9 @@ class ListSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
         )
         PropertyFromValueCreator propertyFromValueCreator = new 
PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator)
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
+                binder.getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinderToUse,
                 collectionBinder,
@@ -91,8 +91,6 @@ class ListSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         )
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, binder.getMappingCacheHolder(), 
componentPropertyBinder)
-        componentPropertyBinder.setComponentBinder(componentBinder)
 
         GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
@@ -107,7 +105,7 @@ class ListSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 manyToOneBinder,
                 propertyFromValueCreator
         )
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder)
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder)
         PropertyBinder propertyBinderHelper = new PropertyBinder()
         SimpleIdBinder simpleIdBinder = new 
SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new 
BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, 
compositeIdBinder)
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/MapSecondPassBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/MapSecondPassBinderSpec.groovy
index 951d1d31c2..8e4f59702a 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/MapSecondPassBinderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/MapSecondPassBinderSpec.groovy
@@ -20,7 +20,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
-import 
org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentPropertyBinder
 import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
 import org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator
 import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder
@@ -80,8 +79,9 @@ class MapSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
         )
         PropertyFromValueCreator propertyFromValueCreator = new 
PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new 
ComponentUpdater(propertyFromValueCreator)
-        ComponentPropertyBinder componentPropertyBinder = new 
ComponentPropertyBinder(
+        ComponentBinder componentBinder = new ComponentBinder(
                 metadataBuildingContext,
+                binder.getMappingCacheHolder(),
                 collectionHolder,
                 enumTypeBinderToUse,
                 collectionBinder,
@@ -91,8 +91,6 @@ class MapSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 columnNameForPropertyAndPathFetcher,
                 componentUpdater
         )
-        ComponentBinder componentBinder = new 
ComponentBinder(metadataBuildingContext, binder.getMappingCacheHolder(), 
componentPropertyBinder)
-        componentPropertyBinder.setComponentBinder(componentBinder)
 
         GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder(
                 metadataBuildingContext,
@@ -107,7 +105,7 @@ class MapSecondPassBinderSpec extends 
HibernateGormDatastoreSpec {
                 manyToOneBinder,
                 propertyFromValueCreator
         )
-        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentPropertyBinder)
+        CompositeIdBinder compositeIdBinder = new 
CompositeIdBinder(metadataBuildingContext, componentBinder)
         PropertyBinder propertyBinderHelper = new PropertyBinder()
         SimpleIdBinder simpleIdBinder = new 
SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new 
BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, 
compositeIdBinder)

Reply via email to