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 0e11f81a1787e62a121890acb91dd70023ac4796
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Wed Jul 9 20:20:00 2025 -0500

    refactoring and testing NamingStrategyProvider
---
 .../orm/hibernate/cfg/GrailsDomainBinder.java      |  78 ++++++--------
 .../cfg/domainbinding/NamingStrategyProvider.java  |  75 +++++++++++++
 .../NamingStrategyProviderSpec.groovy              | 116 +++++++++++++++++++++
 3 files changed, 221 insertions(+), 48 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 14084c1902..8a61ddb898 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
@@ -36,12 +36,12 @@ import org.grails.datastore.mapping.reflect.NameUtils;
 import org.grails.orm.hibernate.access.TraitPropertyAccessStrategy;
 import org.grails.orm.hibernate.cfg.domainbinding.ClassBinder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.ConfigureDerivedPropertiesConsumer;
+import org.grails.orm.hibernate.cfg.domainbinding.NamingStrategyProvider;
 import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider;
 import org.hibernate.FetchMode;
 import org.hibernate.MappingException;
 import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
 import org.hibernate.boot.model.internal.BinderHelper;
-import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
 import org.hibernate.boot.model.naming.Identifier;
 import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
 import org.hibernate.boot.spi.AccessType;
@@ -144,14 +144,13 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private static final String DEFAULT_ENUM_TYPE = "default";
     private static final Logger LOG = 
LoggerFactory.getLogger(GrailsDomainBinder.class);
     public static final String SEQUENCE_KEY = "sequence";
+
+
+
     /**
-     * Overrideable naming strategy. Defaults to 
<code>ImprovedNamingStrategy</code> but can
-     * be configured in DataSource.groovy via <code>hibernate.naming_strategy 
= ...</code>.
+     * Provider for naming strategies
      */
-    public static Map<String, PhysicalNamingStrategy> NAMING_STRATEGIES = new 
HashMap<>();
-    static {
-        NAMING_STRATEGIES.put(ConnectionSource.DEFAULT, new 
CamelCaseToUnderscoresNamingStrategy());
-    }
+    private static final NamingStrategyProvider NAMING_STRATEGY_PROVIDER = new 
NamingStrategyProvider();
 
     private final CollectionType CT = new CollectionType(null, this) {
         public Collection create(ToMany property, PersistentClass owner, 
String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) 
{
@@ -167,6 +166,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private PersistentEntityNamingStrategy namingStrategy;
     private MetadataBuildingContext metadataBuildingContext;
 
+
     public JdbcEnvironment getJdbcEnvironment() {
         return  
metadataBuildingContext.getMetadataCollector().getDatabase().getJdbcEnvironment();
     }
@@ -200,6 +200,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
     }
 
+
     /**
      * The default mapping defined by {@link 
org.grails.datastore.mapping.config.Settings#SETTING_DEFAULT_MAPPING}
      * @param defaultMapping The default mapping
@@ -269,23 +270,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
      * @throws IllegalAccessException When an error occurred instantiating the 
strategy
      */
     public static void configureNamingStrategy(final String datasourceName, 
final Object strategy) throws ClassNotFoundException, InstantiationException, 
IllegalAccessException {
-        Class<?> namingStrategyClass = null;
-        PhysicalNamingStrategy namingStrategy;
-        if (strategy instanceof Class<?>) {
-            namingStrategyClass = (Class<?>)strategy;
-        }
-        else if (strategy instanceof CharSequence) {
-            namingStrategyClass = 
Thread.currentThread().getContextClassLoader().loadClass(strategy.toString());
-        }
-
-        if (namingStrategyClass == null) {
-            namingStrategy = (PhysicalNamingStrategy)strategy;
-        }
-        else {
-            namingStrategy = 
(PhysicalNamingStrategy)namingStrategyClass.newInstance();
-        }
-
-        NAMING_STRATEGIES.put(datasourceName, namingStrategy);
+        NAMING_STRATEGY_PROVIDER.configureNamingStrategy(datasourceName, 
strategy);
     }
 
     private void bindMapSecondPass(ToMany property, InFlightMetadataCollector 
mappings,
@@ -732,7 +717,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private void bindCollectionWithJoinTable(ToMany property,
                                                InFlightMetadataCollector 
mappings, Collection collection, PropertyConfig config, String 
sessionFactoryBeanName) {
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
 
         SimpleValue element;
         final boolean isBasicCollectionType = property instanceof Basic;
@@ -757,11 +742,9 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 columnName = config.getJoinTable().getColumn().getName();
             }
             else {
-
-
-                var s = 
namingStrategy.toPhysicalColumnName(toIdentifier(className),getJdbcEnvironment());
-                var p = 
namingStrategy.toPhysicalColumnName(toIdentifier(property.getName()),getJdbcEnvironment());
-                columnName = isEnum ? s.toString() : 
addUnderscore(p.toString(), s.toString());
+                var clazz = 
namingStrategy.toPhysicalColumnName(toIdentifier(className),getJdbcEnvironment());
+                var prop = 
namingStrategy.toPhysicalTableName(toIdentifier(property.getName()),getJdbcEnvironment());
+                columnName = isEnum ? clazz.toString() : 
addUnderscore(prop.toString(), clazz.toString());
             }
 
             if (isEnum) {
@@ -1174,7 +1157,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
         PropertyConfig config = getPropertyConfig(property);
         JoinTable jt = config != null ? config.getJoinTable() : null;
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
         String s = calculateTableForMany(property, sessionFactoryBeanName);
         String tableName = (jt != null && jt.getName() != null ? jt.getName() 
: 
namingStrategy.toPhysicalTableName(toIdentifier(s),getJdbcEnvironment()).toString());
         String schemaName = getSchemaName(mappings);
@@ -1203,7 +1186,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
      * where you have two mapping tables for left_right and right_left
      */
     private String calculateTableForMany(ToMany property, String 
sessionFactoryBeanName) {
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
 
         String propertyColumnName = 
namingStrategy.toPhysicalColumnName(toIdentifier(property.getName()), 
getJdbcEnvironment()).toString();
         //fix for GRAILS-5895
@@ -1285,20 +1268,18 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                 tableName = namingStrategy.resolveTableName(domainClass);
             }
             if(tableName == null) {
-                tableName = 
getNamingStrategy(sessionFactoryBeanName).toPhysicalTableName(toIdentifier(shortName),getJdbcEnvironment()).toString();
+                tableName = 
getPhysicalNamingStrategy(sessionFactoryBeanName).toPhysicalTableName(toIdentifier(shortName),getJdbcEnvironment()).toString();
             }
         }
         return tableName;
     }
 
-    private PhysicalNamingStrategy getNamingStrategy(String 
sessionFactoryBeanName) {
-        String key = "sessionFactory".equals(sessionFactoryBeanName) ?
-                ConnectionSource.DEFAULT :
-                sessionFactoryBeanName.substring("sessionFactory_".length());
-        PhysicalNamingStrategy namingStrategy = NAMING_STRATEGIES.get(key);
-        return namingStrategy != null ? namingStrategy : new 
CamelCaseToUnderscoresNamingStrategy();
+    private PhysicalNamingStrategy getPhysicalNamingStrategy(String 
sessionFactoryBeanName) {
+        return 
NAMING_STRATEGY_PROVIDER.getPhysicalNamingStrategy(sessionFactoryBeanName);
     }
 
+
+
     /**
      * Binds a Grails domain class to the Hibernate runtime meta model
      *
@@ -1377,7 +1358,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
      * @return A Mapping object or null
      */
     private static Mapping getMapping(PersistentEntity domainClass) {
-        return domainClass == null ? null : 
AbstractGrailsDomainBinder.getMapping(domainClass.getJavaClass());
+        return getMapping(domainClass.getJavaClass());
     }
 
     public static void clearMappingCache() {
@@ -1770,7 +1751,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
         var isAbstract = !m.getTablePerHierarchy() && 
m.isTablePerConcreteClass() && root.isAbstract();
         // create the table
-        Table table = mappings.addTable(schema
+        var table = mappings.addTable(schema
                 , catalog
                 , getTableName(domainClass, sessionFactoryBeanName)
                 , null
@@ -2325,7 +2306,8 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private void bindManyToOne(Association property, ManyToOne manyToOne,
                                  String path, InFlightMetadataCollector 
mappings, String sessionFactoryBeanName) {
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
+
 
         bindManyToOneValues(property, manyToOne);
         PersistentEntity refDomainClass = property instanceof ManyToMany ? 
property.getOwner() : property.getAssociatedEntity();
@@ -2374,7 +2356,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
                                                       SimpleValue value, 
CompositeIdentity compositeId, PersistentEntity refDomainClass,
                                                       String path, String 
sessionFactoryBeanName) {
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
 
         String[] propertyNames = compositeId.getPropertyNames();
         PropertyConfig config = getPropertyConfig(property);
@@ -3095,7 +3077,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private String getColumnNameForPropertyAndPath(PersistentProperty 
grailsProp,
                                                      String path, ColumnConfig 
cc, String sessionFactoryBeanName) {
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
 
         // First try the column config.
         String columnName = null;
@@ -3150,7 +3132,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
 
     private String getDefaultColumnName(PersistentProperty property, String 
sessionFactoryBeanName) {
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
 
         String columnName = 
namingStrategy.toPhysicalColumnName(toIdentifier(property.getName()), 
getJdbcEnvironment()).toString();
         if (property instanceof Association) {
@@ -3187,7 +3169,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
     private String getForeignKeyForPropertyDomainClass(PersistentProperty 
property,
                                                          String 
sessionFactoryBeanName) {
         final String propertyName = NameUtils.decapitalize( 
property.getOwner().getName() );
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
         return namingStrategy.toPhysicalColumnName(toIdentifier(propertyName), 
getJdbcEnvironment()).toString() + FOREIGN_KEY_SUFFIX;
     }
 
@@ -3196,7 +3178,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
         if (pc != null && pc.getIndexColumn() != null && 
pc.getIndexColumn().getColumn() != null) {
             return pc.getIndexColumn().getColumn();
         }
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
         return 
namingStrategy.toPhysicalColumnName(toIdentifier(property.getName()), 
getJdbcEnvironment()).toString() + UNDERSCORE + 
IndexedCollection.DEFAULT_INDEX_COLUMN_NAME;
     }
 
@@ -3217,7 +3199,7 @@ public class GrailsDomainBinder implements 
MetadataContributor {
             return pc.getJoinTable().getColumn().getName();
         }
 
-        PhysicalNamingStrategy namingStrategy = 
getNamingStrategy(sessionFactoryBeanName);
+        PhysicalNamingStrategy namingStrategy = 
getPhysicalNamingStrategy(sessionFactoryBeanName);
         return 
namingStrategy.toPhysicalColumnName(toIdentifier(property.getName()), 
getJdbcEnvironment()).toString() + UNDERSCORE + 
IndexedCollection.DEFAULT_ELEMENT_COLUMN_NAME;
     }
 
diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProvider.java
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProvider.java
new file mode 100644
index 0000000000..05821b9e79
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProvider.java
@@ -0,0 +1,75 @@
+package org.grails.orm.hibernate.cfg.domainbinding;
+
+import org.grails.datastore.mapping.core.connections.ConnectionSource;
+import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
+import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class NamingStrategyProvider {
+    private final ConcurrentHashMap<String, PhysicalNamingStrategy> 
physicalProviderMap;
+
+    public NamingStrategyProvider() {
+        physicalProviderMap = new ConcurrentHashMap<>();
+        physicalProviderMap.put(ConnectionSource.DEFAULT, new 
CamelCaseToUnderscoresNamingStrategy());
+    }
+
+    /**
+     * Configures the naming strategy for a given datasource.
+     *
+     * @param datasourceName the datasource name
+     * @param strategy the naming strategy (instance, Class, or class name)
+     * @throws ClassNotFoundException when the strategy class cannot be found
+     * @throws IllegalAccessException when the strategy class cannot be 
accessed
+     * @throws InstantiationException when the strategy class cannot be 
instantiated
+     */
+    public void configureNamingStrategy(final String datasourceName, final 
Object strategy)
+            throws ClassNotFoundException, InstantiationException, 
IllegalAccessException {
+
+        if (strategy == null) {
+            throw new IllegalArgumentException("Naming strategy cannot be 
null");
+        }
+
+        var strategyClass = getStrategyClass(strategy);
+        var strategyInstance = getStrategyInstance(strategy, strategyClass);
+
+        if (strategyInstance instanceof PhysicalNamingStrategy 
physicalStrategy) {
+            physicalProviderMap.put(datasourceName, physicalStrategy);
+        } else {
+           physicalProviderMap.put(datasourceName, new 
CamelCaseToUnderscoresNamingStrategy());
+        }
+    }
+
+    private Class<?> getStrategyClass(Object strategy) throws 
ClassNotFoundException {
+        if (strategy instanceof Class<?>) {
+            return (Class<?>) strategy;
+        }
+        if (strategy instanceof CharSequence) {
+            return 
Thread.currentThread().getContextClassLoader().loadClass(strategy.toString());
+        }
+        return strategy.getClass();
+    }
+
+    private Object getStrategyInstance(Object strategy, Class<?> strategyClass)
+            throws InstantiationException, IllegalAccessException {
+        if (strategy instanceof PhysicalNamingStrategy) {
+            return strategy;
+        }
+        return strategyClass.newInstance();
+    }
+
+    public PhysicalNamingStrategy getPhysicalNamingStrategy(String 
sessionFactoryBeanName) {
+        String key = getKey(sessionFactoryBeanName);
+        physicalProviderMap.putIfAbsent(key, new 
CamelCaseToUnderscoresNamingStrategy());
+        return physicalProviderMap.get(key);
+    }
+
+
+    private static String getKey(String sessionFactoryBeanName) {
+        String key = "sessionFactory".equals(sessionFactoryBeanName) ?
+                ConnectionSource.DEFAULT :
+                sessionFactoryBeanName.substring("sessionFactory_".length());
+        return key;
+    }
+
+}
diff --git 
a/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProviderSpec.groovy
 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProviderSpec.groovy
new file mode 100644
index 0000000000..ac4f1260c8
--- /dev/null
+++ 
b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/NamingStrategyProviderSpec.groovy
@@ -0,0 +1,116 @@
+package org.grails.orm.hibernate.cfg.domainbinding
+
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
+import org.hibernate.boot.model.naming.PhysicalNamingStrategy
+
+class NamingStrategyProviderSpec extends HibernateGormDatastoreSpec {
+
+    void "Test constructor initializes with default strategy"() {
+        when:
+        def provider = new NamingStrategyProvider()
+        def strategy = provider.getPhysicalNamingStrategy("sessionFactory")
+
+        then:
+        strategy instanceof CamelCaseToUnderscoresNamingStrategy
+    }
+
+    void "Test configureNamingStrategy with null strategy throws exception"() {
+        given:
+        def provider = new NamingStrategyProvider()
+
+        when:
+        provider.configureNamingStrategy("test", null)
+
+        then:
+        thrown(IllegalArgumentException)
+    }
+
+    void "Test configureNamingStrategy with PhysicalNamingStrategy instance"() 
{
+        given:
+        def provider = new NamingStrategyProvider()
+        def mockStrategy = new MockPhysicalNamingStrategy()
+
+        when:
+        provider.configureNamingStrategy("test", mockStrategy)
+        def strategy = 
provider.getPhysicalNamingStrategy("sessionFactory_test")
+
+        then:
+        strategy instanceof MockPhysicalNamingStrategy
+    }
+
+    void "Test configureNamingStrategy with Class"() {
+        given:
+        def provider = new NamingStrategyProvider()
+
+        when:
+        provider.configureNamingStrategy("test", MockPhysicalNamingStrategy)
+        def strategy = 
provider.getPhysicalNamingStrategy("sessionFactory_test")
+
+        then:
+        strategy instanceof MockPhysicalNamingStrategy
+    }
+
+    void "Test configureNamingStrategy with class name"() {
+        given:
+        def provider = new NamingStrategyProvider()
+
+        when:
+        provider.configureNamingStrategy("test", 
MockPhysicalNamingStrategy.name)
+        def strategy = 
provider.getPhysicalNamingStrategy("sessionFactory_test")
+
+        then:
+        strategy instanceof MockPhysicalNamingStrategy
+    }
+
+    void "Test getPhysicalNamingStrategy with default session factory"() {
+        given:
+        def provider = new NamingStrategyProvider()
+
+        when:
+        def strategy = provider.getPhysicalNamingStrategy("sessionFactory")
+
+        then:
+        strategy instanceof CamelCaseToUnderscoresNamingStrategy
+    }
+
+    void "Test getPhysicalNamingStrategy with custom session factory"() {
+        given:
+        def provider = new NamingStrategyProvider()
+        def mockStrategy = new MockPhysicalNamingStrategy()
+        provider.configureNamingStrategy("custom", mockStrategy)
+
+        when:
+        def strategy = 
provider.getPhysicalNamingStrategy("sessionFactory_custom")
+
+        then:
+        strategy instanceof MockPhysicalNamingStrategy
+    }
+}
+
+class MockPhysicalNamingStrategy implements PhysicalNamingStrategy {
+    @Override
+    org.hibernate.boot.model.naming.Identifier 
toPhysicalCatalogName(org.hibernate.boot.model.naming.Identifier name, 
org.hibernate.engine.jdbc.env.spi.JdbcEnvironment jdbcEnvironment) {
+        return name
+    }
+
+    @Override
+    org.hibernate.boot.model.naming.Identifier 
toPhysicalSchemaName(org.hibernate.boot.model.naming.Identifier name, 
org.hibernate.engine.jdbc.env.spi.JdbcEnvironment jdbcEnvironment) {
+        return name
+    }
+
+    @Override
+    org.hibernate.boot.model.naming.Identifier 
toPhysicalTableName(org.hibernate.boot.model.naming.Identifier name, 
org.hibernate.engine.jdbc.env.spi.JdbcEnvironment jdbcEnvironment) {
+        return name
+    }
+
+    @Override
+    org.hibernate.boot.model.naming.Identifier 
toPhysicalSequenceName(org.hibernate.boot.model.naming.Identifier name, 
org.hibernate.engine.jdbc.env.spi.JdbcEnvironment jdbcEnvironment) {
+        return name
+    }
+
+    @Override
+    org.hibernate.boot.model.naming.Identifier 
toPhysicalColumnName(org.hibernate.boot.model.naming.Identifier name, 
org.hibernate.engine.jdbc.env.spi.JdbcEnvironment jdbcEnvironment) {
+        return name
+    }
+}

Reply via email to