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 e68727c2056bc24d404c43af8b1b4e98110a2b6c Author: Walter Duque de Estrada <[email protected]> AuthorDate: Thu Feb 19 12:28:22 2026 -0600 Extract SubclassMappingBinder and add spec --- .../domainbinding/binder/GrailsDomainBinder.java | 41 +------- .../binder/SubclassMappingBinder.java | 71 +++++++++++++ .../binder/SubclassMappingBinderSpec.groovy | 111 +++++++++++++++++++++ 3 files changed, 184 insertions(+), 39 deletions(-) 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 c9133b9675..1943517cf5 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 @@ -288,7 +288,8 @@ public class GrailsDomainBinder @Nonnull InFlightMetadataCollector mappings, Mapping m, MappingCacheHolder mappingCacheHolder, DefaultColumnNameFetcher defaultColumnNameFetcher, ClassBinder classBinder, ClassPropertiesBinder classPropertiesBinder, MultiTenantFilterBinder multiTenantFilterBinder, JoinedSubClassBinder joinedSubClassBinder, UnionSubclassBinder unionSubclassBinder, SingleTableSubclassBinder singleTableSubclassBinder) { mappingCacheHolder.cacheMapping(sub); - Subclass subClass = createSubclassMapping(sub, parent, mappings, m, defaultColumnNameFetcher, classPropertiesBinder, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder); + SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder); + Subclass subClass = subclassMappingBinder.createSubclassMapping(sub, parent, mappings, m); parent.addSubclass(subClass); @@ -303,44 +304,6 @@ public class GrailsDomainBinder } } - private @NonNull Subclass createSubclassMapping(@NonNull GrailsHibernatePersistentEntity subEntity - , PersistentClass parent - , @NonNull InFlightMetadataCollector mappings - , Mapping m - , DefaultColumnNameFetcher defaultColumnNameFetcher - ,ClassPropertiesBinder classPropertiesBinder - ,JoinedSubClassBinder joinedSubClassBinder - , UnionSubclassBinder unionSubclassBinder - , SingleTableSubclassBinder singleTableSubclassBinder) { - Subclass subClass; - subEntity.configureDerivedProperties(); - if (!m.getTablePerHierarchy() && !m.isTablePerConcreteClass()) { - var joined = new JoinedSubclass(parent, this.metadataBuildingContext); - joinedSubClassBinder.bindJoinedSubClass(subEntity, joined, mappings); - subClass = joined; - } - else if(m.isTablePerConcreteClass()) { - var union = new UnionSubclass(parent, this.metadataBuildingContext); - unionSubclassBinder.bindUnionSubclass(subEntity, union, mappings); - subClass = union; - } - else { - var singleTableSubclass = new SingleTableSubclass(parent, this.metadataBuildingContext); - - singleTableSubclassBinder.bindSubClass(subEntity, singleTableSubclass, mappings); - subClass = singleTableSubclass; - } - subClass.setBatchSize(Optional.ofNullable(m.getBatchSize()).orElse(-1)); - subClass.setDynamicUpdate(m.getDynamicUpdate()); - subClass.setDynamicInsert(m.getDynamicInsert()); - subClass.setCached(parent.isCached()); - subClass.setAbstract(subEntity.isAbstract()); - subClass.setEntityName(subEntity.getName()); - subClass.setJpaEntityName(GrailsHibernateUtil.unqualify(subEntity.getName())); - classPropertiesBinder.bindClassProperties(subEntity, subClass, mappings); - return subClass; - } - /** * Binds a sub-class using table-per-hierarchy inheritance mapping diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinder.java new file mode 100644 index 0000000000..67ff7438cf --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinder.java @@ -0,0 +1,71 @@ +package org.grails.orm.hibernate.cfg.domainbinding.binder; + +import jakarta.annotation.Nonnull; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.grails.orm.hibernate.cfg.GrailsHibernateUtil; +import org.grails.orm.hibernate.cfg.Mapping; +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.mapping.JoinedSubclass; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.SingleTableSubclass; +import org.hibernate.mapping.Subclass; +import org.hibernate.mapping.UnionSubclass; + +import java.util.Optional; + +public class SubclassMappingBinder { + + private final MetadataBuildingContext metadataBuildingContext; + private final JoinedSubClassBinder joinedSubClassBinder; + private final UnionSubclassBinder unionSubclassBinder; + private final SingleTableSubclassBinder singleTableSubclassBinder; + private final ClassPropertiesBinder classPropertiesBinder; + + public SubclassMappingBinder( + MetadataBuildingContext metadataBuildingContext, + JoinedSubClassBinder joinedSubClassBinder, + UnionSubclassBinder unionSubclassBinder, + SingleTableSubclassBinder singleTableSubclassBinder, + ClassPropertiesBinder classPropertiesBinder) { + this.metadataBuildingContext = metadataBuildingContext; + this.joinedSubClassBinder = joinedSubClassBinder; + this.unionSubclassBinder = unionSubclassBinder; + this.singleTableSubclassBinder = singleTableSubclassBinder; + this.classPropertiesBinder = classPropertiesBinder; + } + + public @NonNull Subclass createSubclassMapping(@NonNull GrailsHibernatePersistentEntity subEntity + , PersistentClass parent + , @NonNull InFlightMetadataCollector mappings + , Mapping m) { + Subclass subClass; + subEntity.configureDerivedProperties(); + if (!m.getTablePerHierarchy() && !m.isTablePerConcreteClass()) { + var joined = new JoinedSubclass(parent, this.metadataBuildingContext); + joinedSubClassBinder.bindJoinedSubClass(subEntity, joined, mappings); + subClass = joined; + } + else if(m.isTablePerConcreteClass()) { + var union = new UnionSubclass(parent, this.metadataBuildingContext); + unionSubclassBinder.bindUnionSubclass(subEntity, union, mappings); + subClass = union; + } + else { + var singleTableSubclass = new SingleTableSubclass(parent, this.metadataBuildingContext); + + singleTableSubclassBinder.bindSubClass(subEntity, singleTableSubclass, mappings); + subClass = singleTableSubclass; + } + subClass.setBatchSize(Optional.ofNullable(m.getBatchSize()).orElse(-1)); + subClass.setDynamicUpdate(m.getDynamicUpdate()); + subClass.setDynamicInsert(m.getDynamicInsert()); + subClass.setCached(parent.isCached()); + subClass.setAbstract(subEntity.isAbstract()); + subClass.setEntityName(subEntity.getName()); + subClass.setJpaEntityName(GrailsHibernateUtil.unqualify(subEntity.getName())); + classPropertiesBinder.bindClassProperties(subEntity, subClass, mappings); + return subClass; + } +} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinderSpec.groovy new file mode 100644 index 0000000000..3936ae8e3e --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubclassMappingBinderSpec.groovy @@ -0,0 +1,111 @@ +package org.grails.orm.hibernate.cfg.domainbinding.binder + +import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec +import org.grails.orm.hibernate.cfg.Mapping +import org.hibernate.boot.spi.MetadataBuildingContext +import org.hibernate.mapping.JoinedSubclass +import org.hibernate.mapping.PersistentClass +import org.hibernate.mapping.RootClass +import org.hibernate.mapping.SingleTableSubclass +import org.hibernate.mapping.Subclass +import org.hibernate.mapping.UnionSubclass +import spock.lang.Shared + +class SubclassMappingBinderSpec extends HibernateGormDatastoreSpec { + + SubclassMappingBinder binder + MetadataBuildingContext metadataBuildingContext + JoinedSubClassBinder joinedSubClassBinder + UnionSubclassBinder unionSubclassBinder + SingleTableSubclassBinder singleTableSubclassBinder + ClassPropertiesBinder classPropertiesBinder + + void setup() { + manager.addAllDomainClasses([SMBSDefaultSuperEntity, SMBSDefaultSubEntity]) + def gdb = getGrailsDomainBinder() + metadataBuildingContext = gdb.getMetadataBuildingContext() + joinedSubClassBinder = Mock(JoinedSubClassBinder) + unionSubclassBinder = Mock(UnionSubclassBinder) + singleTableSubclassBinder = Mock(SingleTableSubclassBinder) + classPropertiesBinder = Mock(ClassPropertiesBinder) + + binder = new SubclassMappingBinder( + metadataBuildingContext, + joinedSubClassBinder, + unionSubclassBinder, + singleTableSubclassBinder, + classPropertiesBinder + ) + } + + def "test createSubclassMapping for single table inheritance"() { + given: + def subEntity = createPersistentEntity(SMBSDefaultSubEntity) as org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(SMBSDefaultSuperEntity.name) + def mappings = getCollector() + def mapping = new Mapping() + mapping.setTablePerHierarchy(true) + + when: + Subclass subClass = binder.createSubclassMapping(subEntity, rootClass, mappings, mapping) + + then: + 1 * singleTableSubclassBinder.bindSubClass(subEntity, _ as SingleTableSubclass, mappings) + 1 * classPropertiesBinder.bindClassProperties(subEntity, _ as Subclass, mappings) + subClass instanceof SingleTableSubclass + subClass.getEntityName() == SMBSDefaultSubEntity.name + } + + def "test createSubclassMapping for joined table inheritance"() { + given: + def subEntity = getPersistentEntity(SMBSDefaultSubEntity) as org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(SMBSDefaultSuperEntity.name) + def mappings = getCollector() + def mapping = new Mapping() + mapping.@tablePerHierarchy = false + mapping.@tablePerConcreteClass = false + + when: + Subclass subClass = binder.createSubclassMapping(subEntity, rootClass, mappings, mapping) + + then: + 1 * joinedSubClassBinder.bindJoinedSubClass(subEntity, _ as JoinedSubclass, mappings) + 1 * classPropertiesBinder.bindClassProperties(subEntity, _ as Subclass, mappings) + subClass instanceof JoinedSubclass + subClass.getEntityName() == SMBSDefaultSubEntity.name + } + + def "test createSubclassMapping for table per concrete class inheritance"() { + given: + def subEntity = getPersistentEntity(SMBSDefaultSubEntity) as org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity + def rootClass = new RootClass(metadataBuildingContext) + rootClass.setEntityName(SMBSDefaultSuperEntity.name) + def mappings = getCollector() + def mapping = new Mapping() + mapping.@tablePerHierarchy = false + mapping.@tablePerConcreteClass = true + + when: + Subclass subClass = binder.createSubclassMapping(subEntity, rootClass, mappings, mapping) + + then: + 1 * unionSubclassBinder.bindUnionSubclass(subEntity, _ as UnionSubclass, mappings) + 1 * classPropertiesBinder.bindClassProperties(subEntity, _ as Subclass, mappings) + subClass instanceof UnionSubclass + subClass.getEntityName() == SMBSDefaultSubEntity.name + } +} + +@Entity +class SMBSDefaultSuperEntity { + Long id + String name +} + +@Entity +class SMBSDefaultSubEntity extends SMBSDefaultSuperEntity { + String subName +}
