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 4fca2af57919571ee50b1ef9cbb1b2d7d13839cd Author: Walter Duque de Estrada <[email protected]> AuthorDate: Thu Feb 19 12:14:07 2026 -0600 Extract DiscriminatorPropertyBinder and add spec --- .../binder/DiscriminatorPropertyBinder.java | 85 +++++++++++++++ .../domainbinding/binder/GrailsDomainBinder.java | 54 +--------- .../binder/DiscriminatorPropertyBinderSpec.groovy | 120 +++++++++++++++++++++ 3 files changed, 207 insertions(+), 52 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinder.java new file mode 100644 index 0000000000..bc584521aa --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinder.java @@ -0,0 +1,85 @@ +package org.grails.orm.hibernate.cfg.domainbinding.binder; + +import org.grails.orm.hibernate.cfg.ColumnConfig; +import org.grails.orm.hibernate.cfg.DiscriminatorConfig; +import org.grails.orm.hibernate.cfg.Mapping; +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.mapping.BasicValue; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Formula; +import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.SimpleValue; +import org.hibernate.mapping.Table; + +import static org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder.JPA_DEFAULT_DISCRIMINATOR_TYPE; + +public class DiscriminatorPropertyBinder { + + private static final String STRING_TYPE = "string"; + + private final MetadataBuildingContext metadataBuildingContext; + private final SimpleValueColumnBinder simpleValueColumnBinder; + private final ColumnConfigToColumnBinder columnConfigToColumnBinder; + + public DiscriminatorPropertyBinder( + MetadataBuildingContext metadataBuildingContext, + SimpleValueColumnBinder simpleValueColumnBinder, + ColumnConfigToColumnBinder columnConfigToColumnBinder) { + this.metadataBuildingContext = metadataBuildingContext; + this.simpleValueColumnBinder = simpleValueColumnBinder; + this.columnConfigToColumnBinder = columnConfigToColumnBinder; + } + + /** + * Creates and binds the discriminator property used in table-per-hierarchy inheritance to + * discriminate between sub class instances + * + * @param entity The root class entity + * @param someMapping The mappings instance + */ + public void bindDiscriminatorProperty(RootClass entity, Mapping someMapping) { + Table table = entity.getTable(); + SimpleValue d = new BasicValue(metadataBuildingContext, table); + entity.setDiscriminator(d); + DiscriminatorConfig discriminatorConfig = someMapping.getDiscriminator(); + + boolean hasDiscriminatorConfig = discriminatorConfig != null; + entity.setDiscriminatorValue(hasDiscriminatorConfig ? discriminatorConfig.getValue() : entity.getClassName()); + + String typeName = STRING_TYPE; + if(hasDiscriminatorConfig) { + if (discriminatorConfig.getInsertable() != null) { + entity.setDiscriminatorInsertable(discriminatorConfig.getInsertable()); + } + Object type = discriminatorConfig.getType(); + if (type != null) { + if(type instanceof Class) { + typeName = ((Class)type).getName(); + } + else { + typeName = type.toString(); + } + } + } + + + if (hasDiscriminatorConfig && discriminatorConfig.getFormula() != null) { + d.setTypeName(typeName); + Formula formula = new Formula(); + formula.setFormula(discriminatorConfig.getFormula()); + d.addFormula(formula); + } + else{ + simpleValueColumnBinder.bindSimpleValue(d, typeName, JPA_DEFAULT_DISCRIMINATOR_TYPE, false); + + ColumnConfig cc = !hasDiscriminatorConfig ? null : discriminatorConfig.getColumn(); + if (cc != null) { + Column c = (Column) d.getColumns().iterator().next(); + if (cc.getName() != null) { + c.setName(cc.getName()); + } + columnConfigToColumnBinder.bindColumnConfigToColumn(c, cc, null); + } + } + } +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java index 05323e231f..c9133b9675 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java @@ -255,7 +255,8 @@ public class GrailsDomainBinder Mapping m = entity.getMappedForm(); final Mapping finalMapping = m; if (!children.isEmpty() && entity.isTablePerHierarchy()) { - bindDiscriminatorProperty(root, m); + DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, new SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()); + discriminatorPropertyBinder.bindDiscriminatorProperty(root, m); } // bind the sub classes children.forEach(sub -> bindSubClass(sub, root, mappings, finalMapping,mappingCacheHolder, defaultColumnNameFetcher, classBinder, classPropertiesBinder, multiTenantFilterBinder, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder)); @@ -348,57 +349,6 @@ public class GrailsDomainBinder * @param subClass The Hibernate SubClass instance * @param mappings The mappings instance */ - /** - * Creates and binds the discriminator property used in table-per-hierarchy inheritance to - * discriminate between sub class instances - * - * @param entity The root class entity - * @param someMapping The mappings instance - */ - private void bindDiscriminatorProperty(RootClass entity, Mapping someMapping) { - Table table = entity.getTable(); - SimpleValue d = new BasicValue(metadataBuildingContext, table); - entity.setDiscriminator(d); - DiscriminatorConfig discriminatorConfig = someMapping.getDiscriminator(); - - boolean hasDiscriminatorConfig = discriminatorConfig != null; - entity.setDiscriminatorValue(hasDiscriminatorConfig ? discriminatorConfig.getValue() : entity.getClassName()); - - if(hasDiscriminatorConfig) { - if (discriminatorConfig.getInsertable() != null) { - entity.setDiscriminatorInsertable(discriminatorConfig.getInsertable()); - } - Object type = discriminatorConfig.getType(); - if (type != null) { - if(type instanceof Class) { - d.setTypeName(((Class)type).getName()); - } - else { - d.setTypeName(type.toString()); - } - } - } - - - if (hasDiscriminatorConfig && discriminatorConfig.getFormula() != null) { - Formula formula = new Formula(); - formula.setFormula(discriminatorConfig.getFormula()); - d.addFormula(formula); - } - else{ - new SimpleValueColumnBinder().bindSimpleValue(d, STRING_TYPE, JPA_DEFAULT_DISCRIMINATOR_TYPE, false); - - ColumnConfig cc = !hasDiscriminatorConfig ? null : discriminatorConfig.getColumn(); - if (cc != null) { - Column c = (Column) d.getColumns().iterator().next(); - if (cc.getName() != null) { - c.setName(cc.getName()); - } - new ColumnConfigToColumnBinder().bindColumnConfigToColumn(c, cc, null); - } - } - } - public MetadataBuildingContext getMetadataBuildingContext() { return metadataBuildingContext; } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinderSpec.groovy new file mode 100644 index 0000000000..e63f76b4d3 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/DiscriminatorPropertyBinderSpec.groovy @@ -0,0 +1,120 @@ +package org.grails.orm.hibernate.cfg.domainbinding.binder + +import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec +import org.grails.orm.hibernate.cfg.DiscriminatorConfig +import org.grails.orm.hibernate.cfg.Mapping +import org.grails.orm.hibernate.cfg.PropertyConfig +import org.hibernate.boot.spi.MetadataBuildingContext +import org.hibernate.mapping.Formula +import org.hibernate.mapping.RootClass +import org.hibernate.mapping.SimpleValue +import org.hibernate.mapping.Table +import spock.lang.Shared + +class DiscriminatorPropertyBinderSpec extends HibernateGormDatastoreSpec { + + DiscriminatorPropertyBinder binder + MetadataBuildingContext metadataBuildingContext + + void setup() { + manager.addAllDomainClasses([DiscriminatorTestEntity]) + def gdb = getGrailsDomainBinder() + metadataBuildingContext = gdb.getMetadataBuildingContext() + binder = new DiscriminatorPropertyBinder( + metadataBuildingContext, + new SimpleValueColumnBinder(), + new ColumnConfigToColumnBinder() + ) + } + + def "test bindDiscriminatorProperty with default values"() { + given: + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(DiscriminatorTestEntity.name) + rootClass.setClassName(DiscriminatorTestEntity.name) + rootClass.setTable(new Table("DISCRIMINATOR_TEST_ENTITY")) + def mapping = new Mapping() + + when: + binder.bindDiscriminatorProperty(rootClass, mapping) + + then: + rootClass.getDiscriminator() != null + rootClass.getDiscriminatorValue() == DiscriminatorTestEntity.name + rootClass.getDiscriminator().getTypeName() == "string" + rootClass.getDiscriminator().getColumnSpan() == 1 + rootClass.getDiscriminator().getColumns().iterator().next().getName() == GrailsDomainBinder.JPA_DEFAULT_DISCRIMINATOR_TYPE + } + + def "test bindDiscriminatorProperty with custom value"() { + given: + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(DiscriminatorTestEntity.name) + rootClass.setClassName(DiscriminatorTestEntity.name) + rootClass.setTable(new Table("DISCRIMINATOR_TEST_ENTITY")) + def mapping = new Mapping() + mapping.setDiscriminator(new DiscriminatorConfig(value: "CUSTOM_VALUE")) + + when: + binder.bindDiscriminatorProperty(rootClass, mapping) + + then: + rootClass.getDiscriminatorValue() == "CUSTOM_VALUE" + } + + def "test bindDiscriminatorProperty with custom type"() { + given: + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(DiscriminatorTestEntity.name) + rootClass.setClassName(DiscriminatorTestEntity.name) + rootClass.setTable(new Table("DISCRIMINATOR_TEST_ENTITY")) + def mapping = new Mapping() + mapping.setDiscriminator(new DiscriminatorConfig(type: "integer")) + + when: + binder.bindDiscriminatorProperty(rootClass, mapping) + + then: + rootClass.getDiscriminator().getTypeName() == "integer" + } + + def "test bindDiscriminatorProperty with formula"() { + given: + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(DiscriminatorTestEntity.name) + rootClass.setClassName(DiscriminatorTestEntity.name) + rootClass.setTable(new Table("DISCRIMINATOR_TEST_ENTITY")) + def mapping = new Mapping() + mapping.setDiscriminator(new DiscriminatorConfig(formula: "case when type=1 then 'A' else 'B' end")) + + when: + binder.bindDiscriminatorProperty(rootClass, mapping) + + then: + rootClass.getDiscriminator().getSelectables().iterator().next() instanceof Formula + ((Formula)rootClass.getDiscriminator().getSelectables().iterator().next()).getFormula() == "case when type=1 then 'A' else 'B' end" + } + + def "test bindDiscriminatorProperty with custom column name"() { + given: + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(DiscriminatorTestEntity.name) + rootClass.setClassName(DiscriminatorTestEntity.name) + rootClass.setTable(new Table("DISCRIMINATOR_TEST_ENTITY")) + def mapping = new Mapping() + mapping.setDiscriminator(new DiscriminatorConfig(column: [name: "MY_DISCRIMINATOR"])) + + when: + binder.bindDiscriminatorProperty(rootClass, mapping) + + then: + rootClass.getDiscriminator().getColumns().iterator().next().getName() == "MY_DISCRIMINATOR" + } +} + +@Entity +class DiscriminatorTestEntity { + Long id + String name +}
