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 d654ad1655272c33d61de17ba4fb774e55a025fa Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Jul 12 21:50:53 2025 -0500 refactor IndexBinder --- .../orm/hibernate/cfg/GrailsDomainBinder.java | 101 +++++---------------- .../hibernate/cfg/domainbinding/IndexBinder.java | 26 ++++++ .../cfg/domainbinding/IndexBinderSpec.groovy | 90 ++++++++++++++++++ 3 files changed, 138 insertions(+), 79 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 5cf0186fbe..db87d77c68 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 @@ -37,6 +37,7 @@ import org.grails.orm.hibernate.access.TraitPropertyAccessStrategy; 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.IndexBinder; import org.grails.orm.hibernate.cfg.domainbinding.NamingStrategyProvider; import org.grails.orm.hibernate.cfg.domainbinding.SimpleValueBinder; import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider; @@ -284,11 +285,10 @@ public class GrailsDomainBinder implements MetadataContributor { String type = getIndexColumnType(property, STRING_TYPE); String columnName1 = getIndexColumnName(property, sessionFactoryBeanName); new SimpleValueBinder().bindSimpleValue(value, type, columnName1, true); - PropertyConfig pc = getPropertyConfig(property); - if (pc != null && pc.getIndexColumn() != null) { + PropertyConfig mappedForm = getPropertyConfig(property); + if (mappedForm != null && mappedForm.getIndexColumn() != null) { Column column = getColumnForSimpleValue(value); - ColumnConfig columnConfig = getSingleColumnConfig(pc.getIndexColumn()); - final PropertyConfig mappedForm = getPropertyConfig(property); + ColumnConfig columnConfig = getSingleColumnConfig(mappedForm.getIndexColumn()); new ColumnConfigToColumnBinder().bindColumnConfigToColumn(column, columnConfig, mappedForm); } @@ -1269,6 +1269,7 @@ public class GrailsDomainBinder implements MetadataContributor { + /** * Binds a Grails domain class to the Hibernate runtime meta model * @@ -2111,7 +2112,7 @@ public class GrailsDomainBinder implements MetadataContributor { PropertyConfig propertyConfig = getPropertyConfig(property); if (propertyConfig != null && !propertyConfig.getColumns().isEmpty()) { ColumnConfig columnConfig = propertyConfig.getColumns().get(0); - bindIndex(columnName, column, columnConfig, t); + new IndexBinder().bindIndex(columnName, column, columnConfig, t); final PropertyConfig mappedForm = getPropertyConfig(property); new ColumnConfigToColumnBinder().bindColumnConfigToColumn(column, columnConfig, mappedForm); } @@ -2813,7 +2814,7 @@ public class GrailsDomainBinder implements MetadataContributor { String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { setTypeForPropertyConfig(grailsProp, simpleValue, propertyConfig); final PropertyConfig mappedForm = (PropertyConfig) grailsProp.getMapping().getMappedForm(); - if (mappedForm.isDerived() && !(grailsProp instanceof TenantId)) { + if (mappedForm != null && mappedForm.isDerived() && !(grailsProp instanceof TenantId)) { Formula formula = new Formula(); formula.setFormula(propertyConfig.getFormula()); simpleValue.addFormula(formula); @@ -2840,52 +2841,20 @@ public class GrailsDomainBinder implements MetadataContributor { // not all custom mapped properties will have column definitions, // in which case we still need to create a Hibernate column for // this value. - List<?> columnDefinitions = hasConfig ? propertyConfig.getColumns() - : Arrays.asList(new Object[] { null }); - if (columnDefinitions.isEmpty()) { - columnDefinitions = Arrays.asList(new Object[] { null }); - } - - for (Object columnDefinition : columnDefinitions) { - ColumnConfig cc = (ColumnConfig) columnDefinition; - Column column = new Column(); - - // Check for explicitly mapped column name and SQL type. - if (cc != null) { - if (cc.getName() != null) { - column.setName(cc.getName()); - } - if (cc.getSqlType() != null) { - column.setSqlType(cc.getSqlType()); - } - } - - column.setValue(simpleValue); - - - if (cc != null) { - if (cc.getLength() != -1) { - column.setLength(cc.getLength()); - } - if (cc.getPrecision() != -1) { - column.setPrecision(cc.getPrecision()); - } - if (cc.getScale() != -1) { - column.setScale(cc.getScale()); - } - if(!mappedForm.isUniqueWithinGroup()) { - column.setUnique(cc.isUnique()); - } - } - - bindColumn(grailsProp, parentProperty, column, cc, path, table, sessionFactoryBeanName); - - if (table != null) { - table.addColumn(column); - } - - simpleValue.addColumn(column); - } + var columnConfigToColumnBinder = new ColumnConfigToColumnBinder(); + ofNullable(propertyConfig) + .map(PropertyConfig::getColumns) + .filter(columns -> !columns.isEmpty()) + .orElse(Arrays.asList(new ColumnConfig[] { null })) + .forEach( cc -> { + Column column = new Column(); + columnConfigToColumnBinder.bindColumnConfigToColumn(column,cc,mappedForm); + bindColumn(grailsProp, parentProperty, column, cc, path, table, sessionFactoryBeanName); + if (table != null) { + table.addColumn(column); + } + simpleValue.addColumn(column); + }); } } @@ -2966,7 +2935,7 @@ public class GrailsDomainBinder implements MetadataContributor { handleUniqueConstraint(property, column, path, table, columnName, sessionFactoryBeanName); - bindIndex(columnName, column, cc, table); + new IndexBinder().bindIndex(columnName, column, cc, table); final PersistentEntity owner = property.getOwner(); if (!owner.isRoot()) { @@ -3017,32 +2986,6 @@ public class GrailsDomainBinder implements MetadataContributor { table.addUniqueKey(uk); } - private void bindIndex(String columnName, Column column, ColumnConfig cc, Table table) { - if (cc == null) { - return; - } - - Object indexObj = cc.getIndex(); - String indexDefinition = null; - if (indexObj instanceof Boolean) { - Boolean b = (Boolean) indexObj; - if (b) { - indexDefinition = table.getName() + '_' + columnName + "_idx"; - } - } - else if (indexObj != null) { - indexDefinition = indexObj.toString(); - } - if (indexDefinition == null) { - return; - } - - String[] tokens = indexDefinition.split(","); - for (String index : tokens) { - table.getOrCreateIndex(index).addColumn(column); - } - } - private String getColumnNameForPropertyAndPath(PersistentProperty grailsProp, String path, ColumnConfig cc, String sessionFactoryBeanName) { diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinder.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinder.java new file mode 100644 index 0000000000..da654bf363 --- /dev/null +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinder.java @@ -0,0 +1,26 @@ +package org.grails.orm.hibernate.cfg.domainbinding; + +import org.grails.orm.hibernate.cfg.ColumnConfig; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Table; +import static java.lang.String.format; +import static java.util.Optional.*; + +public class IndexBinder { + public void bindIndex(String columnName, Column column, ColumnConfig cc, Table table) { + ofNullable(cc) + .map(ColumnConfig::getIndex) + .flatMap(indexObj -> { + if (indexObj instanceof Boolean b) { + return b ? of(format("%s_%s_idx", table.getName(), columnName)) : empty(); + } + return of(indexObj.toString()); + }) + .map(def -> def.split(",")) + .ifPresent(indices -> { + for (String index : indices) { + table.getOrCreateIndex(index.trim()).addColumn(column); + } + }); + } +} diff --git a/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinderSpec.groovy b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinderSpec.groovy new file mode 100644 index 0000000000..6ba548370b --- /dev/null +++ b/grails-data-hibernate6/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IndexBinderSpec.groovy @@ -0,0 +1,90 @@ +package org.grails.orm.hibernate.cfg.domainbinding + +import org.grails.orm.hibernate.cfg.ColumnConfig +import org.hibernate.mapping.Column +import org.hibernate.mapping.Index +import org.hibernate.mapping.Table +import spock.lang.Specification + +class IndexBinderSpec extends Specification { + + def indexBinder = new IndexBinder() + def table = Mock(Table) + def column = Mock(Column) + def index = Mock(Index) + + def "should not create index when ColumnConfig is null"() { + when: + indexBinder.bindIndex("colName", column, null, table) + + then: + 0 * table._ // verifies no interactions with table + } + + def "should create default index when index is true"() { + given: + def cc = new ColumnConfig() + cc.index = true + table.getName() >> "test_table" + + when: + indexBinder.bindIndex("test_column", column, cc, table) + + then: + 1 * table.getOrCreateIndex("test_table_test_column_idx") >> index + 1 * index.addColumn(column) + } + + def "should not create index when index is false"() { + given: + def cc = new ColumnConfig() + cc.index = false + + when: + indexBinder.bindIndex("test_column", column, cc, table) + + then: + 0 * table.getOrCreateIndex(_) + 0 * index.addColumn(_) + } + + def "should create multiple indices when comma-separated string is provided"() { + given: + def cc = new ColumnConfig() + cc.index = "idx_one,idx_two" + + when: + indexBinder.bindIndex("test_column", column, cc, table) + + then: + 1 * table.getOrCreateIndex("idx_one") >> index + 1 * table.getOrCreateIndex("idx_two") >> index + 2 * index.addColumn(column) + } + + def "should create single index when string value is provided"() { + given: + def cc = new ColumnConfig() + cc.index = "custom_idx" + + when: + indexBinder.bindIndex("test_column", column, cc, table) + + then: + 1 * table.getOrCreateIndex("custom_idx") >> index + 1 * index.addColumn(column) + } + + def "should not create index when index value is null"() { + given: + def cc = new ColumnConfig() + cc.index = null + + when: + indexBinder.bindIndex("test_column", column, cc, table) + + then: + 0 * table.getOrCreateIndex(_) + 0 * index.addColumn(_) + } +} \ No newline at end of file
