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 38a0436db516aba4b0488b200a2e4f9e6effebc4 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Wed Feb 11 10:41:18 2026 -0600 standardized schema and catalog assignment --- .../orm/hibernate/cfg/GrailsDomainBinder.java | 47 ++++++++-------------- .../cfg/domainbinding/IdentityBinder.java | 37 ++++------------- .../cfg/domainbinding/SimpleIdBinder.java | 28 +++++++++---- .../domainbinding/GrailsPropertyBinderSpec.groovy | 22 +++++----- .../cfg/domainbinding/IdentityBinderSpec.groovy | 27 ++----------- .../cfg/domainbinding/SimpleIdBinderSpec.groovy | 36 +++++++++++++---- 6 files changed, 86 insertions(+), 111 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 26209287af..a88c0b8695 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -16,7 +16,6 @@ package org.grails.orm.hibernate.cfg; import groovy.lang.Closure; -import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.datastore.mapping.model.types.TenantId; import org.grails.orm.hibernate.cfg.domainbinding.ClassBinder; @@ -269,7 +268,7 @@ public class GrailsDomainBinder Collections.emptyMap() ); - Property property = collectionBinder.grailsDomainBinder.getProperty(persistentClass, tenantId.getName()); + Property property = getProperty(persistentClass, tenantId.getName()); if (property.getValue() instanceof BasicValue basicValue) { JdbcMapping jdbcMapping = basicValue.resolve().getJdbcMapping(); var stringVMap = Collections.singletonMap(GormProperties.TENANT_IDENTITY, jdbcMapping); @@ -320,7 +319,7 @@ public class GrailsDomainBinder subEntity.configureDerivedProperties(); if (!m.getTablePerHierarchy() && !m.isTablePerConcreteClass()) { subClass = new JoinedSubclass(parent, this.metadataBuildingContext); - bindJoinedSubClass(subEntity, (JoinedSubclass) subClass, mappings, m, sessionFactoryBeanName); + bindJoinedSubClass(subEntity, (JoinedSubclass) subClass, mappings, sessionFactoryBeanName); } else if(m.isTablePerConcreteClass()) { subClass = new UnionSubclass(parent, this.metadataBuildingContext); @@ -346,26 +345,15 @@ public class GrailsDomainBinder @Nonnull InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { classBinding.bindClass(subClass, unionSubclass, mappings); - Mapping subMapping = subClass.getMappedForm(); - - //TODO Verify if needed at all -// if ( unionSubclass.getEntityPersisterClass() == null ) { -// unionSubclass.getRootClass().setEntityPersisterClass( -// UnionSubclassEntityPersister.class ); -// } - - String schema = subMapping != null && subMapping.getTable().getSchema() != null ? - subMapping.getTable().getSchema() : null; - - String catalog = subMapping != null && subMapping.getTable().getCatalog() != null ? - subMapping.getTable().getCatalog() : null; + String schema = subClass.getSchema(mappings); + String catalog = subClass.getCatalog(mappings); Table denormalizedSuperTable = unionSubclass.getSuperclass().getTable(); Table mytable = mappings.addDenormalizedTable( schema, catalog, new TableNameFetcher(getNamingStrategy()).getTableName(subClass), - unionSubclass.isAbstract() != null && unionSubclass.isAbstract(), + Boolean.TRUE.equals(unionSubclass.isAbstract()), null, denormalizedSuperTable, metadataBuildingContext ); @@ -383,22 +371,21 @@ public class GrailsDomainBinder /** * Binds a joined sub-class mapping using table-per-subclass * - * @param sub The Grails sub class - * @param joinedSubclass The Hibernate Subclass object - * @param mappings The mappings Object - * @param gormMapping The GORM mapping object - * @param sessionFactoryBeanName the session factory bean name + * @param sub The Grails sub class + * @param joinedSubclass The Hibernate Subclass object + * @param mappings The mappings Object + * @param sessionFactoryBeanName the session factory bean name */ private void bindJoinedSubClass(GrailsHibernatePersistentEntity sub, JoinedSubclass joinedSubclass, - InFlightMetadataCollector mappings, Mapping gormMapping, String sessionFactoryBeanName) { + InFlightMetadataCollector mappings, String sessionFactoryBeanName) { classBinding.bindClass(sub, joinedSubclass, mappings); - String schemaName = NamespaceNameExtractor.getSchemaName(mappings); - String catalogName = NamespaceNameExtractor.getCatalogName(mappings); + String schemaName = sub.getSchema(mappings); + String catalogName = sub.getCatalog(mappings); Table mytable = mappings.addTable( schemaName, catalogName, - getJoinedSubClassTableName(sub, joinedSubclass, null, mappings, sessionFactoryBeanName), + getJoinedSubClassTableName(sub, joinedSubclass, null, mappings), null, false, metadataBuildingContext); joinedSubclass.setTable(mytable); @@ -420,13 +407,13 @@ public class GrailsDomainBinder private String getJoinedSubClassTableName( GrailsHibernatePersistentEntity sub, PersistentClass model, Table denormalizedSuperTable, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + InFlightMetadataCollector mappings) { String logicalTableName = GrailsHibernateUtil.unqualify(model.getEntityName()); String physicalTableName = new TableNameFetcher(getNamingStrategy()).getTableName(sub); - String schemaName = NamespaceNameExtractor.getSchemaName(mappings); - String catalogName = NamespaceNameExtractor.getCatalogName(mappings); + String schemaName = sub.getSchema(mappings); + String catalogName = sub.getCatalog(mappings); mappings.addTableNameBinding(schemaName, catalogName, logicalTableName, physicalTableName, denormalizedSuperTable); return physicalTableName; @@ -637,7 +624,7 @@ public class GrailsDomainBinder } - public Property getProperty(PersistentClass associatedClass, String propertyName) throws MappingException { + private Property getProperty(PersistentClass associatedClass, String propertyName) throws MappingException { try { return associatedClass.getProperty(propertyName); } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinder.java index 5c6e7dfb89..baec012d8e 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinder.java @@ -9,6 +9,7 @@ import org.hibernate.mapping.RootClass; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.orm.hibernate.cfg.CompositeIdentity; import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity; +import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty; import org.grails.orm.hibernate.cfg.HibernateIdentity; import org.grails.orm.hibernate.cfg.Identity; import org.grails.orm.hibernate.cfg.Mapping; @@ -45,37 +46,15 @@ public class IdentityBinder { Mapping gormMapping, String sessionFactoryBeanName) { - if (gormMapping != null) { - HibernateIdentity id = gormMapping.getIdentity(); - if (id instanceof CompositeIdentity) { - compositeIdBinder.bindCompositeId(domainClass, root, (CompositeIdentity) id, mappings, sessionFactoryBeanName); - } else { - final Identity identity = (Identity) id; - PersistentProperty identifierProp = domainClass.getIdentity(); - String propertyName = identity.getName(); - if (propertyName != null && !propertyName.equals(domainClass.getName())) { - PersistentProperty namedIdentityProp = domainClass.getPropertyByName(propertyName); - if (namedIdentityProp == null) { - throw new MappingException("Mapping specifies an identifier property name that doesn't exist [" + propertyName + "]"); - } - if (!namedIdentityProp.equals(identifierProp)) { - identifierProp = namedIdentityProp; - } - } - if (identity.getName() == null) { - identity.setName(root.getEntityName()); - } - simpleIdBinder.bindSimpleId(identifierProp, root, identity); - } + HibernateIdentity id = gormMapping != null ? gormMapping.getIdentity() : null; + if (id instanceof CompositeIdentity || (id == null && domainClass.getCompositeIdentity() != null)) { + compositeIdBinder.bindCompositeId(domainClass, root, (CompositeIdentity) id, mappings, sessionFactoryBeanName); } else { - if (domainClass.getCompositeIdentity() != null) { - compositeIdBinder.bindCompositeId(domainClass, root, null, mappings, sessionFactoryBeanName); - } else { - PersistentProperty identifierProp = domainClass.getIdentity(); - if (identifierProp != null) { - simpleIdBinder.bindSimpleId(identifierProp, root, null); - } + Identity identity = id instanceof Identity ? (Identity) id : null; + if (identity != null && identity.getName() == null) { + identity.setName(root.getEntityName()); } + simpleIdBinder.bindSimpleId(domainClass, root, identity); } } } \ No newline at end of file diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java index 0c761eca73..5a89875a3c 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java @@ -8,6 +8,9 @@ import org.hibernate.mapping.Property; import org.hibernate.mapping.RootClass; import org.hibernate.mapping.Table; +import jakarta.annotation.Nonnull; +import org.hibernate.MappingException; + import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty; import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity; @@ -46,27 +49,36 @@ public class SimpleIdBinder { } - public void bindSimpleId(PersistentProperty identifier, RootClass entity, Identity mappedId) { + public void bindSimpleId(@Nonnull GrailsHibernatePersistentEntity domainClass, RootClass entity, Identity mappedId) { - Mapping result = null; - GrailsHibernatePersistentEntity domainClass = null; - if (identifier.getOwner() instanceof GrailsHibernatePersistentEntity) { - domainClass = (GrailsHibernatePersistentEntity) identifier.getOwner(); - result = domainClass.getMappedForm(); - } + Mapping result = domainClass.getMappedForm(); boolean useSequence = result != null && result.isTablePerConcreteClass(); // create the id value BasicValueIdCreator idCreator = this.basicValueIdCreator != null ? this.basicValueIdCreator : new BasicValueIdCreator(metadataBuildingContext, jdbcEnvironment, domainClass, entity); BasicValue id = idCreator.getBasicValueId(mappedId, useSequence); + var identifier = domainClass.getIdentity(); + if (mappedId != null) { + String propertyName = mappedId.getName(); + if (propertyName != null && !propertyName.equals(domainClass.getName())) { + var namedIdentityProp = (GrailsHibernatePersistentProperty) domainClass.getPropertyByName(propertyName); + if (namedIdentityProp == null) { + throw new MappingException("Mapping specifies an identifier property name that doesn't exist [" + propertyName + "]"); + } + if (!namedIdentityProp.equals(identifier)) { + identifier = namedIdentityProp; + } + } + } + Property idProperty = new Property(); idProperty.setName(identifier.getName()); idProperty.setValue(id); entity.setDeclaredIdentifierProperty(idProperty); entity.setIdentifier(id); // set type - simpleValueBinder.bindSimpleValue((GrailsHibernatePersistentProperty) identifier, null, id, EMPTY_PATH); + simpleValueBinder.bindSimpleValue(identifier, null, id, EMPTY_PATH); // create property Property prop = new Property(); diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy index 57005abbb9..ac75f72584 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy @@ -298,7 +298,11 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { def enumTypeBinder = Mock(EnumTypeBinder) def componentPropertyBinder = Mock(ComponentPropertyBinder) def collectionBinder = Mock(CollectionBinder) - def propertyFromValueCreator = Mock(PropertyFromValueCreator) // Mock propertyFromValueCreator as it is a constructor parameter + def propertyFromValueCreator = Mock(PropertyFromValueCreator) + def simpleValueBinder = Mock(SimpleValueBinder) + def columnNameForPropertyAndPathFetcher = Mock(ColumnNameForPropertyAndPathFetcher) + def oneToOneBinder = Mock(OneToOneBinder) + def manyToOneBinder = Mock(ManyToOneBinder) // Instantiate GrailsPropertyBinder using the protected constructor with necessary mocks def propertyBinder = new GrailsPropertyBinder( @@ -308,7 +312,10 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { enumTypeBinder, componentPropertyBinder, collectionBinder, - propertyFromValueCreator + simpleValueBinder, + columnNameForPropertyAndPathFetcher, + oneToOneBinder, + manyToOneBinder ) def mappings = Mock(org.hibernate.boot.spi.InFlightMetadataCollector) @@ -330,17 +337,6 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { currentGrailsProp.getOwner() >> mockOwner mockOwner.isRoot() >> true // Stub isRoot() to prevent NPE in ColumnBinder - // Mock PropertyConfig and stub its methods for SimpleValueBinder - def propertyConfigMock = Mock(PropertyConfig) - currentGrailsProp.getMappedForm() >> propertyConfigMock // For SimpleValueBinder logic, need PropertyConfig - - propertyConfigMock.getGenerator() >> null - propertyConfigMock.getTypeParams() >> new Properties() - propertyConfigMock.isDerived() >> false - def columnConfigMock = Mock(ColumnConfig) // Mock ColumnConfig for getColumns() - columnConfigMock.getName() >> "test_column" // Provide a column name to prevent NPE - propertyConfigMock.getColumns() >> Arrays.asList(columnConfigMock) - // Mocking other necessary properties of currentGrailsProp currentGrailsProp.getType() >> String.class currentGrailsProp.getName() >> "title" diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinderSpec.groovy index a282a80533..61b2bda2d4 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/IdentityBinderSpec.groovy @@ -36,7 +36,7 @@ class IdentityBinderSpec extends HibernateGormDatastoreSpec { binder.bindIdentity(domainClass, root, mappings, null, "sessionFactory") then: - 1 * simpleIdBinder.bindSimpleId(identifierProp, root, null) + 1 * simpleIdBinder.bindSimpleId(domainClass, root, null) } def "should delegate to compositeIdBinder when mapping is null and domainClass has composite identity"() { @@ -87,25 +87,7 @@ class IdentityBinderSpec extends HibernateGormDatastoreSpec { binder.bindIdentity(domainClass, root, mappings, gormMapping, "sessionFactory") then: - 1 * simpleIdBinder.bindSimpleId(identifierProp, root, identity) - } - - def "should throw MappingException when mapping specifies a non-existent identifier property"() { - given: - def domainClass = Mock(GrailsHibernatePersistentEntity) - def root = new RootClass(getGrailsDomainBinder().getMetadataBuildingContext()) - def mappings = Mock(InFlightMetadataCollector) - def gormMapping = Mock(Mapping) - def identity = new Identity(name: "nonExistent") - gormMapping.getIdentity() >> identity - domainClass.getName() >> "MyEntity" - domainClass.getPropertyByName("nonExistent") >> null - - when: - binder.bindIdentity(domainClass, root, mappings, gormMapping, "sessionFactory") - - then: - thrown(org.hibernate.MappingException) + 1 * simpleIdBinder.bindSimpleId(domainClass, root, identity) } def "should not lookup property by name if identity name matches domain class name"() { @@ -124,8 +106,7 @@ class IdentityBinderSpec extends HibernateGormDatastoreSpec { binder.bindIdentity(domainClass, root, mappings, gormMapping, "sessionFactory") then: - 0 * domainClass.getPropertyByName(_) - 1 * simpleIdBinder.bindSimpleId(identifierProp, root, identity) + 1 * simpleIdBinder.bindSimpleId(domainClass, root, identity) } def "should set entity name on identity if it is null"() { @@ -146,6 +127,6 @@ class IdentityBinderSpec extends HibernateGormDatastoreSpec { then: identity.getName() == "MyEntity" - 1 * simpleIdBinder.bindSimpleId(identifierProp, root, identity) + 1 * simpleIdBinder.bindSimpleId(domainClass, root, identity) } } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinderSpec.groovy index dfe5cf0d4b..87734e5ba5 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinderSpec.groovy @@ -49,16 +49,18 @@ class SimpleIdBinderSpec extends HibernateGormDatastoreSpec { } def testProperty = Mock(GrailsHibernatePersistentProperty) { getName() >> "id" - getOwner() >> Mock(GrailsHibernatePersistentEntity) { - getMappedForm() >> mapping - } + } + def domainClass = Mock(GrailsHibernatePersistentEntity) { + getMappedForm() >> mapping + getIdentity() >> testProperty + getName() >> "TestEntity" } def rootClass = new RootClass(metadataBuildingContext) currentTable = new Table("TEST_TABLE") rootClass.setTable(currentTable) when: - simpleIdBinder.bindSimpleId(testProperty, rootClass, new Identity(generator: GrailsSequenceGeneratorEnum.IDENTITY.toString())) + simpleIdBinder.bindSimpleId(domainClass, rootClass, new Identity(generator: GrailsSequenceGeneratorEnum.IDENTITY.toString())) then: 1 * simpleValueBinder.bindSimpleValue(testProperty as GrailsHibernatePersistentProperty, null, _, "") @@ -77,16 +79,18 @@ class SimpleIdBinderSpec extends HibernateGormDatastoreSpec { } def testProperty = Mock(GrailsHibernatePersistentProperty) { getName() >> "id" - getOwner() >> Mock(GrailsHibernatePersistentEntity) { - getMappedForm() >> mapping - } + } + def domainClass = Mock(GrailsHibernatePersistentEntity) { + getMappedForm() >> mapping + getIdentity() >> testProperty + getName() >> "TestEntity" } def rootClass = new RootClass(metadataBuildingContext) currentTable = new Table("TEST_TABLE") rootClass.setTable(currentTable) when: - simpleIdBinder.bindSimpleId(testProperty, rootClass, new Identity(generator: GrailsSequenceGeneratorEnum.SEQUENCE.toString(), params: [sequence: 'SEQ_TEST'])) + simpleIdBinder.bindSimpleId(domainClass, rootClass, new Identity(generator: GrailsSequenceGeneratorEnum.SEQUENCE.toString(), params: [sequence: 'SEQ_TEST'])) then: 1 * simpleValueBinder.bindSimpleValue(testProperty as GrailsHibernatePersistentProperty, null, _, "") @@ -97,4 +101,20 @@ class SimpleIdBinderSpec extends HibernateGormDatastoreSpec { rootClass.identifierProperty != null rootClass.table.primaryKey instanceof PrimaryKey } + + def "bindSimpleId with non-existent identifier property"() { + given: + def domainClass = Mock(GrailsHibernatePersistentEntity) { + getName() >> "TestEntity" + getPropertyByName("nonExistent") >> null + getIdentity() >> Mock(GrailsHibernatePersistentProperty) + } + def rootClass = new RootClass(metadataBuildingContext) + + when: + simpleIdBinder.bindSimpleId(domainClass, rootClass, new Identity(name: "nonExistent")) + + then: + thrown(org.hibernate.MappingException) + } } \ No newline at end of file
