This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch merge-hibernate6
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 41a37104467ac25bedcd17c626e8e41b8cf82d3f
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Mon Sep 29 19:34:01 2025 -0500

    More refactoring
---
 .../orm/hibernate/cfg/GrailsDomainBinder.java      | 135 ++-------------
 .../org/grails/orm/hibernate/cfg/Mapping.groovy    |   4 +
 .../ForeignKeyColumnCountCalculator.java           |  28 ++++
 .../cfg/domainbinding/SimpleValueBinder.java       | 119 +++++++++++++
 .../ForeignKeyColumnCountCalculatorSpec.groovy     |  52 ++++++
 .../cfg/domainbinding/SimpleValueBinderSpec.groovy | 184 +++++++++++++++++++++
 6 files changed, 404 insertions(+), 118 deletions(-)

diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
index dd1a546e57..d8df2b6449 100644
--- 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
@@ -33,12 +33,9 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.ClassBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.ColumnConfigToColumnBinder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.ConfigureDerivedPropertiesConsumer;
 import org.grails.orm.hibernate.cfg.domainbinding.EnumTypeBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.IndexBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.NamingStrategyProvider;
-import 
org.grails.orm.hibernate.cfg.domainbinding.NumericColumnConstraintsBinder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.PersistentPropertyToPropertyConfig;
 import org.grails.orm.hibernate.cfg.domainbinding.SimpleValueColumnBinder;
-import 
org.grails.orm.hibernate.cfg.domainbinding.StringColumnConstraintsBinder;
 import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider;
 import org.grails.orm.hibernate.cfg.domainbinding.*;
 import org.hibernate.FetchMode;
@@ -92,7 +89,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.util.StringUtils;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -518,7 +514,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 bindDependentKeyValue(property, key, mappings, 
sessionFactoryBeanName);
             }
         } else {
-            if (hasJoinKeyMapping(propConfig)) {
+            if (propConfig.hasJoinKeyMapping()) {
                 String columnName = 
propConfig.getJoinTable().getKey().getName();
                 new SimpleValueColumnBinder().bindSimpleValue(key, "long", 
columnName, false);
             } else {
@@ -780,7 +776,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
             final PersistentEntity domainClass = 
property.getAssociatedEntity();
 
             Mapping m = new 
HibernateEntityWrapper().getMappedForm(domainClass);
-            if (hasCompositeIdentifier(m)) {
+            if (m.hasCompositeIdentifier()) {
                 CompositeIdentity ci = (CompositeIdentity) m.getIdentity();
                 bindCompositeIdentifierToManyToOne(property, element, ci, 
domainClass,
                         EMPTY_PATH, sessionFactoryBeanName);
@@ -856,7 +852,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
         PersistentEntity refDomainClass = property.getOwner();
         final Mapping mapping = new 
HibernateEntityWrapper().getMappedForm(refDomainClass);
-        boolean hasCompositeIdentifier = hasCompositeIdentifier(mapping);
+        boolean hasCompositeIdentifier = mapping.hasCompositeIdentifier();
         if ((shouldCollectionBindWithJoinColumn((ToMany) property) && 
hasCompositeIdentifier) ||
                 (hasCompositeIdentifier && ( property instanceof ManyToMany))) 
{
             CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity();
@@ -864,7 +860,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
         }
         else {
             // set type
-            bindSimpleValue(property, null, key, EMPTY_PATH, 
sessionFactoryBeanName);
+            new SimpleValueBinder(namingStrategy).bindSimpleValue(property, 
null, key, EMPTY_PATH);
         }
     }
 
@@ -1793,7 +1789,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 }
                 value = new BasicValue(metadataBuildingContext, table);
                 // set type
-                bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, 
EMPTY_PATH, sessionFactoryBeanName);
+                new 
SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null, 
(SimpleValue) value, EMPTY_PATH);
             }
             else if (collectionType != null) {
                 String typeName = new 
TypeNameProvider().getTypeName(currentGrailsProp, gormMapping);
@@ -1861,7 +1857,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 }
                 value = new BasicValue(metadataBuildingContext, table);
                 // set type
-                bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, 
EMPTY_PATH, sessionFactoryBeanName);
+                new 
SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null, 
(SimpleValue) value, EMPTY_PATH);
             }
 
             if (value != null) {
@@ -1998,7 +1994,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
             }
             else {
                 // set type
-                bindSimpleValue(currentGrailsProp, componentProperty, 
(SimpleValue) value, path, sessionFactoryBeanName);
+                new 
SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, 
componentProperty, (SimpleValue) value, path);
             }
         }
 
@@ -2054,7 +2050,8 @@ public class GrailsDomainBinder implements 
MetadataContributor {
         bindManyToOneValues(property, manyToOne);
         PersistentEntity refDomainClass = property instanceof ManyToMany ? 
property.getOwner() : property.getAssociatedEntity();
         Mapping mapping = new 
HibernateEntityWrapper().getMappedForm(refDomainClass);
-        boolean isComposite = hasCompositeIdentifier(mapping);
+
+        boolean isComposite = mapping.hasCompositeIdentifier();
         if (isComposite) {
             CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity();
             bindCompositeIdentifierToManyToOne(property, manyToOne, ci, 
refDomainClass, path, sessionFactoryBeanName);
@@ -2067,7 +2064,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 if (pc.getColumns().isEmpty()) {
                     mapping.getColumns().put(property.getName(), pc);
                 }
-                if (!hasJoinKeyMapping(pc) ) {
+                if (!pc.hasJoinKeyMapping()) {
                     JoinTable jt = new JoinTable();
                     final ColumnConfig columnConfig = new ColumnConfig();
                     
columnConfig.setName(getNamingStrategy().resolveColumnName(property.getName()) 
+ UNDERSCORE + FOREIGN_KEY_SUFFIX);
@@ -2076,12 +2073,12 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 }
                 new PersistentPropertyToPropertyConfig().apply(property);
                 // set type
-                bindSimpleValue(property, null, manyToOne, path, 
sessionFactoryBeanName);
+                new 
SimpleValueBinder(namingStrategy).bindSimpleValue(property, null, manyToOne, 
path);
             }
             else {
                 // bind column
                 // set type
-                bindSimpleValue(property, null, manyToOne, path, 
sessionFactoryBeanName);
+                new 
SimpleValueBinder(namingStrategy).bindSimpleValue(property, null, manyToOne, 
path);
             }
         }
 
@@ -2108,7 +2105,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
         List<ColumnConfig> columns = config.getColumns();
         int i = columns.size();
-        int expectedForeignKeyColumnLength = 
calculateForeignKeyColumnCount(refDomainClass, propertyNames);
+        int expectedForeignKeyColumnLength = new 
ForeignKeyColumnCountCalculator().calculateForeignKeyColumnCount(refDomainClass,
 propertyNames);
         if (i != expectedForeignKeyColumnLength) {
             int j = 0;
             for (String propertyName : propertyNames) {
@@ -2157,35 +2154,11 @@ public class GrailsDomainBinder implements 
MetadataContributor {
         }
         new PersistentPropertyToPropertyConfig().apply(property);
         // set type
-        bindSimpleValue(property, null, value, path, sessionFactoryBeanName);
+        new SimpleValueBinder(namingStrategy).bindSimpleValue(property, null, 
value, path);
     }
 
     // each property may consist of one or many columns (due to composite ids) 
so in order to get the
     // number of columns required for a column key we have to perform the 
calculation here
-    private int calculateForeignKeyColumnCount(PersistentEntity 
refDomainClass, String[] propertyNames) {
-        int expectedForeignKeyColumnLength = 0;
-        for (String propertyName : propertyNames) {
-            PersistentProperty referencedProperty = 
refDomainClass.getPropertyByName(propertyName);
-            if(referencedProperty instanceof ToOne) {
-                ToOne toOne = (ToOne) referencedProperty;
-                PersistentProperty[] compositeIdentity = 
toOne.getAssociatedEntity().getCompositeIdentity();
-                if(compositeIdentity != null) {
-                    expectedForeignKeyColumnLength += compositeIdentity.length;
-                }
-                else {
-                    expectedForeignKeyColumnLength++;
-                }
-            }
-            else {
-                expectedForeignKeyColumnLength++;
-            }
-        }
-        return expectedForeignKeyColumnLength;
-    }
-
-    private boolean hasCompositeIdentifier(Mapping mapping) {
-        return mapping != null && (mapping.getIdentity() instanceof 
CompositeIdentity);
-    }
 
     private void bindOneToOne(final 
org.grails.datastore.mapping.model.types.OneToOne property, OneToOne oneToOne,
                                 String path, String sessionFactoryBeanName) {
@@ -2217,7 +2190,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
             PropertyConfig pc = new 
PersistentPropertyToPropertyConfig().apply(property);
             new PersistentPropertyToPropertyConfig().apply(property);
             // set type
-            bindSimpleValue(property, null, oneToOne, path, 
sessionFactoryBeanName);
+            new SimpleValueBinder(namingStrategy).bindSimpleValue(property, 
null, oneToOne, path);
         }
         else {
             oneToOne.setReferencedPropertyName(otherSide.getName());
@@ -2261,7 +2234,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
             BasicValue val = new BasicValue(metadataBuildingContext, 
entity.getTable());
 
             // set type
-            bindSimpleValue(version, null, val, EMPTY_PATH, 
sessionFactoryBeanName);
+            new SimpleValueBinder(namingStrategy).bindSimpleValue(version, 
null, val, EMPTY_PATH);
 
             if (val.isTypeSpecified()) {
 //                if (!(val.getType() instanceof IntegerType ||
@@ -2341,7 +2314,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
         // bind value
         // set type
-        bindSimpleValue(identifier, null, id, EMPTY_PATH, 
sessionFactoryBeanName);
+        new SimpleValueBinder(namingStrategy).bindSimpleValue(identifier, 
null, id, EMPTY_PATH);
 
         // create property
         Property prop = new Property();
@@ -2357,80 +2330,6 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     }
 
 
-    /**
-     * Binds a simple value to the Hibernate metamodel. A simple value is
-     * any type within the Hibernate type system
-     *
-     * @param property
-     * @param parentProperty
-     * @param simpleValue The simple value to bind
-     * @param path
-     * @param sessionFactoryBeanName  the session factory bean name
-     */
-    private void bindSimpleValue(
-            PersistentProperty property
-            , PersistentProperty parentProperty
-            , SimpleValue simpleValue
-            , String path
-            , String sessionFactoryBeanName
-    ) {
-        PropertyConfig propertyConfig = new 
PersistentPropertyToPropertyConfig().apply(property);
-        Mapping mapping = new 
HibernateEntityWrapper().getMappedForm(property.getOwner());
-        final String typeName = new TypeNameProvider().getTypeName(property, 
mapping);
-        if (typeName == null) {
-            simpleValue.setTypeName(property.getType().getName());
-        }
-        else {
-            simpleValue.setTypeName(typeName);
-            simpleValue.setTypeParameters(propertyConfig.getTypeParams());
-        }
-        if ( propertyConfig.isDerived() && !(property instanceof TenantId)) {
-            Formula formula = new Formula();
-            formula.setFormula(propertyConfig.getFormula());
-            simpleValue.addFormula(formula);
-        } else {
-            Table table = simpleValue.getTable();
-
-            String generator = propertyConfig.getGenerator();
-            if(generator != null) {
-                simpleValue.setIdentifierGeneratorStrategy(generator);
-                Properties params = propertyConfig.getTypeParams();
-                if(params != null) {
-                    Properties generatorProps = new Properties();
-                    generatorProps.putAll(params);
-
-                    if(generatorProps.containsKey(SEQUENCE_KEY)) {
-                        
generatorProps.put(SequenceStyleGenerator.SEQUENCE_PARAM,  
generatorProps.getProperty(SEQUENCE_KEY));
-                    }
-                    simpleValue.setIdentifierGeneratorProperties( 
generatorProps );
-                }
-            }
-
-            // Add the column definitions for this value/property. Note that
-            // not all custom mapped properties will have column definitions,
-            // in which case we still need to create a Hibernate column for
-            // this value.
-            var columnConfigToColumnBinder = new ColumnConfigToColumnBinder();
-            var columnBinder = new ColumnBinder(namingStrategy);
-            Optional.ofNullable(propertyConfig.getColumns()).
-                    filter(list-> !list.isEmpty())
-                    .orElse(Arrays.asList(new ColumnConfig[] { null }))
-                    .forEach( cc -> {
-                        Column column = new Column();
-                        
columnConfigToColumnBinder.bindColumnConfigToColumn(column,cc,propertyConfig);
-                        columnBinder.bindColumn(property, parentProperty, 
column, cc, path, table);
-                        if (table != null) {
-                            table.addColumn(column);
-                        }
-                        simpleValue.addColumn(column);
-                    });
-        }
-    }
-
-    private boolean hasJoinKeyMapping(PropertyConfig c) {
-        return c.hasJoinKeyMapping();
-    }
-
     private String getIndexColumnName(PersistentProperty property, String 
sessionFactoryBeanName) {
         PropertyConfig pc = new 
PersistentPropertyToPropertyConfig().apply(property);
         if (pc != null && pc.getIndexColumn() != null && 
pc.getIndexColumn().getColumn() != null) {
diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
index bb2fe77195..f8171cb0aa 100644
--- 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
@@ -596,4 +596,8 @@ class Mapping extends Entity<PropertyConfig> {
         }
         cloned
     }
+
+    boolean hasCompositeIdentifier() {
+       return identity instanceof CompositeIdentity
+   }
 }
diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculator.java
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculator.java
new file mode 100644
index 0000000000..879ee061e9
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculator.java
@@ -0,0 +1,28 @@
+package org.grails.orm.hibernate.cfg.domainbinding;
+
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PersistentProperty;
+import org.grails.datastore.mapping.model.types.ToOne;
+// each property may consist of one or many columns (due to composite ids) so 
in order to get the
+// number of columns required for a column key we have to perform the 
calculation here
+public class ForeignKeyColumnCountCalculator {
+    public int calculateForeignKeyColumnCount(PersistentEntity refDomainClass, 
String[] propertyNames) {
+        int expectedForeignKeyColumnLength = 0;
+        for (String propertyName : propertyNames) {
+            PersistentProperty referencedProperty = 
refDomainClass.getPropertyByName(propertyName);
+            if(referencedProperty instanceof ToOne toOne) {
+                PersistentProperty[] compositeIdentity = 
toOne.getAssociatedEntity().getCompositeIdentity();
+                if(compositeIdentity != null) {
+                    expectedForeignKeyColumnLength += compositeIdentity.length;
+                }
+                else {
+                    expectedForeignKeyColumnLength++;
+                }
+            }
+            else {
+                expectedForeignKeyColumnLength++;
+            }
+        }
+        return expectedForeignKeyColumnLength;
+    }
+}
diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
new file mode 100644
index 0000000000..94fdaaab5e
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
@@ -0,0 +1,119 @@
+package org.grails.orm.hibernate.cfg.domainbinding;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.hibernate.id.enhanced.SequenceStyleGenerator;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Formula;
+import org.hibernate.mapping.SimpleValue;
+import org.hibernate.mapping.Table;
+
+import org.grails.datastore.mapping.model.PersistentProperty;
+import org.grails.datastore.mapping.model.types.TenantId;
+import org.grails.orm.hibernate.cfg.ColumnConfig;
+import org.grails.orm.hibernate.cfg.Mapping;
+import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy;
+import org.grails.orm.hibernate.cfg.PropertyConfig;
+
+public class SimpleValueBinder {
+
+    private final ColumnConfigToColumnBinder columnConfigToColumnBinder ;
+    private final ColumnBinder columnBinder;
+    private final PersistentPropertyToPropertyConfig 
persistentPropertyToPropertyConfig;
+    private final HibernateEntityWrapper hibernateEntityWrapper;
+    private final TypeNameProvider typeNameProvider;
+
+
+    private static final String SEQUENCE_KEY = "sequence";
+
+    public SimpleValueBinder(PersistentEntityNamingStrategy namingStrategy) {
+        this.columnConfigToColumnBinder = new ColumnConfigToColumnBinder();
+        this.columnBinder = new ColumnBinder(namingStrategy);
+        this.persistentPropertyToPropertyConfig = new 
PersistentPropertyToPropertyConfig();
+        this.hibernateEntityWrapper = new HibernateEntityWrapper();
+        this.typeNameProvider = new TypeNameProvider();
+
+    }
+
+    protected SimpleValueBinder(ColumnConfigToColumnBinder 
columnConfigToColumnBinder
+            , ColumnBinder columnBinder
+            , PersistentPropertyToPropertyConfig 
persistentPropertyToPropertyConfig
+    , HibernateEntityWrapper hibernateEntityWrapper
+    ,TypeNameProvider typeNameProvider) {
+        this.columnConfigToColumnBinder = columnConfigToColumnBinder;
+        this.columnBinder = columnBinder;
+        this.persistentPropertyToPropertyConfig = 
persistentPropertyToPropertyConfig;
+        this.typeNameProvider = typeNameProvider;
+        this.hibernateEntityWrapper = hibernateEntityWrapper;
+    }
+
+
+    /**
+     * Binds a simple value to the Hibernate metamodel. A simple value is
+     * any type within the Hibernate type system
+     *
+     * @param property
+     * @param parentProperty
+     * @param simpleValue    The simple value to bind
+     * @param path
+     */
+
+    public void bindSimpleValue(
+            PersistentProperty property
+            , PersistentProperty parentProperty
+            , SimpleValue simpleValue
+            , String path
+    ) {
+        PropertyConfig propertyConfig = 
persistentPropertyToPropertyConfig.apply(property);
+        Mapping mapping = 
hibernateEntityWrapper.getMappedForm(property.getOwner());
+        final String typeName = typeNameProvider.getTypeName(property, 
mapping);
+        if (typeName == null) {
+            simpleValue.setTypeName(property.getType().getName());
+        }
+        else {
+            simpleValue.setTypeName(typeName);
+            simpleValue.setTypeParameters(propertyConfig.getTypeParams());
+        }
+        if ( propertyConfig.isDerived() && !(property instanceof TenantId)) {
+            Formula formula = new Formula();
+            formula.setFormula(propertyConfig.getFormula());
+            simpleValue.addFormula(formula);
+        } else {
+            Table table = simpleValue.getTable();
+
+            String generator = propertyConfig.getGenerator();
+            if(generator != null) {
+                simpleValue.setIdentifierGeneratorStrategy(generator);
+                Properties params = propertyConfig.getTypeParams();
+                if(params != null) {
+                    Properties generatorProps = new Properties();
+                    generatorProps.putAll(params);
+
+                    if(generatorProps.containsKey(SEQUENCE_KEY)) {
+                        
generatorProps.put(SequenceStyleGenerator.SEQUENCE_PARAM,  
generatorProps.getProperty(SEQUENCE_KEY));
+                    }
+                    simpleValue.setIdentifierGeneratorProperties( 
generatorProps );
+                }
+            }
+
+            // Add the column definitions for this value/property. Note that
+            // not all custom mapped properties will have column definitions,
+            // in which case we still need to create a Hibernate column for
+            // this value.
+            Optional.ofNullable(propertyConfig.getColumns()).
+                    filter(list-> !list.isEmpty())
+                    .orElse(Arrays.asList(new ColumnConfig[] { null }))
+                    .forEach( cc -> {
+                        Column column = new Column();
+                        
columnConfigToColumnBinder.bindColumnConfigToColumn(column,cc,propertyConfig);
+                        columnBinder.bindColumn(property, parentProperty, 
column, cc, path, table);
+                        if (table != null) {
+                            table.addColumn(column);
+                        }
+                        simpleValue.addColumn(column);
+                    });
+        }
+    }
+}
diff --git 
a/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculatorSpec.groovy
 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculatorSpec.groovy
new file mode 100644
index 0000000000..a327560755
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ForeignKeyColumnCountCalculatorSpec.groovy
@@ -0,0 +1,52 @@
+package org.grails.orm.hibernate.cfg.domainbinding
+
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.grails.datastore.mapping.model.PersistentProperty
+import org.grails.datastore.mapping.model.types.ToOne
+import org.grails.orm.hibernate.cfg.HibernatePersistentEntity
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class ForeignKeyColumnCountCalculatorSpec extends Specification {
+
+    @Unroll
+    def "Test calculateForeignKeyColumnCount with #scenario"() {
+        given:
+        def calculator = new ForeignKeyColumnCountCalculator()
+        def refDomainClass = Mock(HibernatePersistentEntity) as 
PersistentEntity
+
+        // Mock for a simple property
+        def simpleProp = Mock(PersistentProperty)
+        refDomainClass.getPropertyByName("simple") >> simpleProp
+
+        // Mocks for a ToOne association with a simple ID
+        def toOneSimpleIdProp = Mock(ToOne)
+        def associatedEntitySimpleId = Mock(HibernatePersistentEntity)
+        refDomainClass.getPropertyByName("toOneSimple") >> toOneSimpleIdProp
+        toOneSimpleIdProp.getAssociatedEntity() >> associatedEntitySimpleId
+        associatedEntitySimpleId.getCompositeIdentity() >> null
+
+        // Mocks for a ToOne association with a composite ID of length 2
+        def toOneCompositeIdProp = Mock(ToOne)
+        def associatedEntityCompositeId = Mock(HibernatePersistentEntity)
+        def compositeId = [Mock(PersistentProperty), Mock(PersistentProperty)] 
as PersistentProperty[]
+        refDomainClass.getPropertyByName("toOneComposite") >> 
toOneCompositeIdProp
+        toOneCompositeIdProp.getAssociatedEntity() >> 
associatedEntityCompositeId
+        associatedEntityCompositeId.getCompositeIdentity() >> compositeId
+
+        when:
+        int columnCount = 
calculator.calculateForeignKeyColumnCount(refDomainClass, propertyNames as 
String[])
+
+        then:
+        columnCount == expectedCount
+
+        where:
+        scenario                                | propertyNames                
                | expectedCount
+        "a single simple property"              | ["simple"]                   
                | 1
+        "a ToOne with a simple ID"              | ["toOneSimple"]              
                | 1
+        "a ToOne with a composite ID"           | ["toOneComposite"]           
                | 2
+        "a mix of all property types"           | ["simple", "toOneSimple", 
"toOneComposite"] | 4
+        "multiple simple properties"            | ["simple", "simple"]         
                | 2
+        "multiple composite ID properties"      | ["toOneComposite", 
"toOneComposite"]         | 4
+    }
+}
diff --git 
a/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
new file mode 100644
index 0000000000..423b496ac5
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
@@ -0,0 +1,184 @@
+package org.grails.orm.hibernate.cfg.domainbinding
+
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.grails.datastore.mapping.model.PersistentProperty
+import org.grails.datastore.mapping.model.types.TenantId
+import org.grails.orm.hibernate.cfg.ColumnConfig
+import org.grails.orm.hibernate.cfg.Mapping
+import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy
+import org.grails.orm.hibernate.cfg.PropertyConfig
+import org.hibernate.id.enhanced.SequenceStyleGenerator
+import org.hibernate.mapping.Column
+import org.hibernate.mapping.SimpleValue
+import org.hibernate.mapping.Table
+import spock.lang.Specification
+
+class SimpleValueBinderSpec extends Specification {
+
+    def namingStrategy = Mock(PersistentEntityNamingStrategy)
+    def columnConfigToColumnBinder = Mock(ColumnConfigToColumnBinder)
+    def columnBinder = Mock(ColumnBinder)
+    def persistentPropertyToPropertyConfig = 
Mock(PersistentPropertyToPropertyConfig)
+    def hibernateEntityWrapper = Mock(HibernateEntityWrapper)
+    def typeNameProvider = Mock(TypeNameProvider)
+
+    def binder = new SimpleValueBinder(columnConfigToColumnBinder,
+            columnBinder,
+            persistentPropertyToPropertyConfig,
+            hibernateEntityWrapper,
+            typeNameProvider)
+
+    def "sets type from provider when present and applies type params"() {
+        given:
+        def prop = Mock(PersistentProperty)
+        def owner = Mock(PersistentEntity)
+        def mapping = Mock(Mapping)
+        def pc = Mock(PropertyConfig)
+        def sv = Mock(SimpleValue)
+        sv.getTable() >> null
+        def props = new Properties(); props.setProperty('p1','v1')
+
+        // stubs
+        persistentPropertyToPropertyConfig.apply(prop) >> pc
+        prop.getOwner() >> owner
+        hibernateEntityWrapper.getMappedForm(owner) >> mapping
+        typeNameProvider.getTypeName(prop, mapping) >> "custom.Type"
+        pc.getTypeParams() >> props
+        pc.isDerived() >> false
+        pc.getColumns() >> null
+        prop.getType() >> String
+        prop.isNullable() >> true
+
+        when:
+        binder.bindSimpleValue(prop, null, sv, "p")
+
+        then:
+        1 * sv.setTypeName("custom.Type")
+        1 * sv.setTypeParameters({ it.getProperty('p1') == 'v1' })
+        1 * columnBinder.bindColumn(prop, null, _ as Column, null, 'p', null)
+        1 * columnConfigToColumnBinder.bindColumnConfigToColumn(_ as Column, 
null, pc)
+    }
+
+    def "falls back to property type when provider returns null"() {
+        given:
+        def prop = Mock(PersistentProperty)
+        def owner = Mock(PersistentEntity)
+        def mapping = Mock(Mapping)
+        def pc = Mock(PropertyConfig)
+        def sv = Mock(SimpleValue)
+        sv.getTable() >> null
+
+        persistentPropertyToPropertyConfig.apply(prop) >> pc
+        prop.getOwner() >> owner
+        hibernateEntityWrapper.getMappedForm(owner) >> mapping
+        typeNameProvider.getTypeName(prop, mapping) >> null
+        pc.isDerived() >> false
+        pc.getColumns() >> null
+        prop.getType() >> Integer
+        prop.isNullable() >> true
+
+        when:
+        binder.bindSimpleValue(prop, null, sv, null)
+
+        then:
+        1 * sv.setTypeName(Integer.name)
+        1 * columnBinder.bindColumn(prop, null, _ as Column, null, null, null)
+    }
+
+    def "derived property adds no columns but adds formula, except TenantId"() 
{
+        given:
+        def prop = Mock(PersistentProperty)
+        def tenantProp = Mock(TenantId)
+        def owner = Mock(PersistentEntity)
+        def mapping = Mock(Mapping)
+        def pc = Mock(PropertyConfig)
+        def tenantPc = Mock(PropertyConfig)
+        def sv = Mock(SimpleValue)
+        def sv2 = Mock(SimpleValue)
+
+        persistentPropertyToPropertyConfig.apply(prop) >> pc
+        persistentPropertyToPropertyConfig.apply(tenantProp) >> tenantPc
+        prop.getOwner() >> owner
+        tenantProp.getOwner() >> owner
+        hibernateEntityWrapper.getMappedForm(owner) >> mapping
+        typeNameProvider.getTypeName(_, _) >> 'X'
+
+        pc.isDerived() >> true
+        pc.getFormula() >> 'x+y'
+        tenantPc.isDerived() >> true
+        tenantPc.getFormula() >> 'ignored'
+
+        when:
+        binder.bindSimpleValue(prop, null, sv, null)
+
+        then:
+        1 * sv.addFormula({ it.getFormula() == 'x+y' })
+        0 * columnBinder.bindColumn(_, _, _, _, _, _)
+
+        when:
+        binder.bindSimpleValue(tenantProp, null, sv2, null)
+
+        then:
+        0 * sv2.addFormula(_)
+        1 * columnBinder.bindColumn(_, _, _ as Column, _, _, _)
+    }
+
+    def "applies generator and maps sequence param to 
SequenceStyleGenerator.SEQUENCE_PARAM"() {
+        given:
+        def prop = Mock(PersistentProperty)
+        def owner = Mock(PersistentEntity)
+        def mapping = Mock(Mapping)
+        def pc = Mock(PropertyConfig)
+        def sv = Mock(SimpleValue)
+        sv.getTable() >> null
+        def genProps = new Properties(); 
genProps.setProperty('sequence','seq_name'); genProps.setProperty('foo','bar')
+
+        persistentPropertyToPropertyConfig.apply(prop) >> pc
+        prop.getOwner() >> owner
+        hibernateEntityWrapper.getMappedForm(owner) >> mapping
+        typeNameProvider.getTypeName(prop, mapping) >> 'Y'
+        pc.isDerived() >> false
+        pc.getColumns() >> null
+        pc.getGenerator() >> 'sequence'
+        pc.getTypeParams() >> genProps
+
+        when:
+        binder.bindSimpleValue(prop, null, sv, null)
+
+        then:
+        1 * sv.setIdentifierGeneratorStrategy('sequence')
+        1 * sv.setIdentifierGeneratorProperties({ 
it.getProperty(SequenceStyleGenerator.SEQUENCE_PARAM) == 'seq_name' && 
it.getProperty('foo') == 'bar' })
+    }
+
+    def "binds for each provided column config and adds to table and simple 
value"() {
+        given:
+        def prop = Mock(PersistentProperty)
+        def parent = Mock(PersistentProperty)
+        def owner = Mock(PersistentEntity)
+        def mapping = Mock(Mapping)
+        def pc = Mock(PropertyConfig)
+        def cc1 = new ColumnConfig(name: 'c1')
+        def cc2 = new ColumnConfig(name: 'c2')
+        def sv = Mock(SimpleValue)
+        sv.getTable() >> null
+
+        persistentPropertyToPropertyConfig.apply(prop) >> pc
+        prop.getOwner() >> owner
+        hibernateEntityWrapper.getMappedForm(owner) >> mapping
+        typeNameProvider.getTypeName(prop, mapping) >> 'Z'
+        pc.isDerived() >> false
+        pc.getColumns() >> [cc1, cc2]
+        prop.isNullable() >> true
+        parent.isNullable() >> false
+
+        when:
+        binder.bindSimpleValue(prop, parent, sv, 'path')
+
+        then:
+        1 * columnConfigToColumnBinder.bindColumnConfigToColumn(_ as Column, 
cc1, pc)
+        1 * columnConfigToColumnBinder.bindColumnConfigToColumn(_ as Column, 
cc2, pc)
+        1 * columnBinder.bindColumn(prop, parent, _ as Column, cc1, 'path', 
null)
+        1 * columnBinder.bindColumn(prop, parent, _ as Column, cc2, 'path', 
null)
+        2 * sv.addColumn(_ as Column)
+    }
+}

Reply via email to