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 21252e9e825838e2b8d43d80fa2dd85b6b53d66b Author: Walter Duque de Estrada <[email protected]> AuthorDate: Tue Feb 17 08:43:53 2026 -0600 Refactor createPrimaryKeyValue into PrimaryKeyValueCreator --- .../cfg/domainbinding/binder/CollectionBinder.java | 4 +- .../secondpass/CollectionSecondPassBinder.java | 41 +---- .../secondpass/PrimaryKeyValueCreator.java | 38 +++++ .../CollectionSecondPassBinderSpec.groovy | 181 --------------------- .../secondpass/PrimaryKeyValueCreatorSpec.groovy | 83 ++++++++++ 5 files changed, 129 insertions(+), 218 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java index 46c2ec5d90..4f451714e0 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java @@ -17,6 +17,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.util.NamespaceNameExtractor; import org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher; import org.grails.orm.hibernate.cfg.domainbinding.util.TableForManyCalculator; import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionSecondPassBinder; +import org.grails.orm.hibernate.cfg.domainbinding.secondpass.PrimaryKeyValueCreator; import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPass; import org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPassBinder; import org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPass; @@ -74,7 +75,8 @@ public class CollectionBinder { enumTypeBinder, manyToOneBinder, compositeIdentifierToManyToOneBinder, - simpleValueColumnFetcher + simpleValueColumnFetcher, + new PrimaryKeyValueCreator(metadataBuildingContext) ); this.listSecondPassBinder = new ListSecondPassBinder(metadataBuildingContext, namingStrategy, collectionSecondPassBinder); this.mapSecondPassBinder = new MapSecondPassBinder(metadataBuildingContext, namingStrategy, collectionSecondPassBinder); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java index 0c5dd65d5b..5f165a7b49 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java @@ -10,7 +10,6 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyP import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty; import org.grails.orm.hibernate.cfg.domainbinding.util.BackticksRemover; -import org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher; import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder; import org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnConfigToColumnBinder; import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder; @@ -57,6 +56,7 @@ public class CollectionSecondPassBinder { private final ManyToOneBinder manyToOneBinder; private final CompositeIdentifierToManyToOneBinder compositeIdentifierToManyToOneBinder; private final SimpleValueColumnFetcher simpleValueColumnFetcher; + private final PrimaryKeyValueCreator primaryKeyValueCreator; public CollectionSecondPassBinder( MetadataBuildingContext metadataBuildingContext, @@ -66,7 +66,8 @@ public class CollectionSecondPassBinder { EnumTypeBinder enumTypeBinder, ManyToOneBinder manyToOneBinder, CompositeIdentifierToManyToOneBinder compositeIdentifierToManyToOneBinder, - SimpleValueColumnFetcher simpleValueColumnFetcher) { + SimpleValueColumnFetcher simpleValueColumnFetcher, + PrimaryKeyValueCreator primaryKeyValueCreator) { this.metadataBuildingContext = metadataBuildingContext; this.namingStrategy = namingStrategy; this.jdbcEnvironment = jdbcEnvironment; @@ -75,18 +76,11 @@ public class CollectionSecondPassBinder { this.manyToOneBinder = manyToOneBinder; this.compositeIdentifierToManyToOneBinder = compositeIdentifierToManyToOneBinder; this.simpleValueColumnFetcher = simpleValueColumnFetcher; + this.primaryKeyValueCreator = primaryKeyValueCreator; this.defaultColumnNameFetcher = new DefaultColumnNameFetcher(namingStrategy); this.orderByClauseBuilder = new OrderByClauseBuilder(); } - public CollectionSecondPassBinder(MetadataBuildingContext metadataBuildingContext, PersistentEntityNamingStrategy namingStrategy, JdbcEnvironment jdbcEnvironment) { - this(metadataBuildingContext, namingStrategy, jdbcEnvironment, - new SimpleValueBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment), - new EnumTypeBinder(metadataBuildingContext, new ColumnNameForPropertyAndPathFetcher(namingStrategy, new DefaultColumnNameFetcher(namingStrategy), new BackticksRemover())), - new ManyToOneBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment), - new CompositeIdentifierToManyToOneBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment), - new SimpleValueColumnFetcher()); - } public void bindCollectionSecondPass(HibernateToManyProperty property, @Nonnull InFlightMetadataCollector mappings, @@ -167,7 +161,7 @@ public class CollectionSecondPassBinder { } // setup the primary key references - DependantValue key = createPrimaryKeyValue(mappings, property, collection); + DependantValue key = primaryKeyValueCreator.createPrimaryKeyValue(collection); // link a bidirectional relationship if (property.isBidirectional()) { @@ -451,29 +445,4 @@ public class CollectionSecondPassBinder { key.setUpdateable(true); } } - - private DependantValue createPrimaryKeyValue(@Nonnull InFlightMetadataCollector mappings, GrailsHibernatePersistentProperty property, - Collection collection) { - KeyValue keyValue; - DependantValue key; - String propertyRef = collection.getReferencedPropertyName(); - // this is to support mapping by a property - if (propertyRef == null) { - keyValue = collection.getOwner().getIdentifier(); - } else { - keyValue = (KeyValue) collection.getOwner().getProperty(propertyRef).getValue(); - } - - if (LOG.isDebugEnabled()) - LOG.debug("[CollectionSecondPassBinder] creating dependant key value to table [" + keyValue.getTable().getName() + "]"); - - key = new DependantValue(metadataBuildingContext, collection.getCollectionTable(), keyValue); - key.setTypeName(null); - key.setNullable(true); - key.setUpdateable(true); - - //JPA now requires to check for sorting - key.setSorted(collection.isSorted()); - return key; - } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreator.java new file mode 100644 index 0000000000..a5781c4a52 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreator.java @@ -0,0 +1,38 @@ +package org.grails.orm.hibernate.cfg.domainbinding.secondpass; + +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.DependantValue; +import org.hibernate.mapping.KeyValue; + +/** + * Creates primary key value for collection. + */ +public class PrimaryKeyValueCreator { + + private final MetadataBuildingContext metadataBuildingContext; + + public PrimaryKeyValueCreator(MetadataBuildingContext metadataBuildingContext) { + this.metadataBuildingContext = metadataBuildingContext; + } + + public DependantValue createPrimaryKeyValue(Collection collection) { + KeyValue keyValue; + String propertyRef = collection.getReferencedPropertyName(); + // this is to support mapping by a property + if (propertyRef == null) { + keyValue = collection.getOwner().getIdentifier(); + } else { + keyValue = (KeyValue) collection.getOwner().getProperty(propertyRef).getValue(); + } + + DependantValue key = new DependantValue(metadataBuildingContext, collection.getCollectionTable(), keyValue); + key.setTypeName(null); + key.setNullable(true); + key.setUpdateable(true); + + //JPA now requires to check for sorting + key.setSorted(collection.isSorted()); + return key; + } +} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy deleted file mode 100644 index e97d42f1ad..0000000000 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionSecondPassBinderSpec.groovy +++ /dev/null @@ -1,181 +0,0 @@ -package org.grails.orm.hibernate.cfg.domainbinding - -import grails.gorm.specs.HibernateGormDatastoreSpec -import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity -import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty -import org.hibernate.mapping.OneToMany -import org.hibernate.mapping.RootClass -import org.hibernate.mapping.Set -import org.hibernate.boot.spi.MetadataBuildingContext -import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy -import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment -import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneValuesBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder -import org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher -import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater -import org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator -import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.IdentityBinder -import org.hibernate.boot.spi.InFlightMetadataCollector -import org.grails.orm.hibernate.cfg.domainbinding.binder.VersionBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleIdBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.PropertyBinder -import org.hibernate.mapping.BasicValue -import org.grails.orm.hibernate.cfg.domainbinding.util.BackticksRemover -import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher -import org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher -import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder -import org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator -import org.grails.orm.hibernate.cfg.GrailsDomainBinder - -import org.grails.orm.hibernate.cfg.domainbinding.binder.ClassPropertiesBinder -import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.JoinedSubClassBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.UnionSubclassBinder -import org.grails.orm.hibernate.cfg.domainbinding.binder.SingleTableSubclassBinder - -class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec { - - protected Map getBinders(GrailsDomainBinder binder) { - MetadataBuildingContext metadataBuildingContext = binder.getMetadataBuildingContext() - PersistentEntityNamingStrategy namingStrategy = binder.getNamingStrategy() - JdbcEnvironment jdbcEnvironment = binder.getJdbcEnvironment() - BackticksRemover backticksRemover = new BackticksRemover() - DefaultColumnNameFetcher defaultColumnNameFetcher = new DefaultColumnNameFetcher(namingStrategy, backticksRemover) - ColumnNameForPropertyAndPathFetcher columnNameForPropertyAndPathFetcher = new ColumnNameForPropertyAndPathFetcher(namingStrategy, defaultColumnNameFetcher, backticksRemover) - CollectionHolder collectionHolder = new CollectionHolder(metadataBuildingContext) - SimpleValueBinder simpleValueBinder = new SimpleValueBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment) - EnumTypeBinder enumTypeBinderToUse = new EnumTypeBinder(metadataBuildingContext, columnNameForPropertyAndPathFetcher) - SimpleValueColumnFetcher simpleValueColumnFetcher = new SimpleValueColumnFetcher() - CompositeIdentifierToManyToOneBinder compositeIdentifierToManyToOneBinder = new CompositeIdentifierToManyToOneBinder( - metadataBuildingContext, - new org.grails.orm.hibernate.cfg.domainbinding.util.ForeignKeyColumnCountCalculator(), - namingStrategy, - defaultColumnNameFetcher, - backticksRemover, - simpleValueBinder - ) - OneToOneBinder oneToOneBinder = new OneToOneBinder(metadataBuildingContext, namingStrategy, simpleValueBinder) - ManyToOneBinder manyToOneBinder = new ManyToOneBinder(metadataBuildingContext, namingStrategy, simpleValueBinder, new ManyToOneValuesBinder(), compositeIdentifierToManyToOneBinder, simpleValueColumnFetcher) - - CollectionBinder collectionBinder = new CollectionBinder( - metadataBuildingContext, - namingStrategy, - jdbcEnvironment, - simpleValueBinder, - enumTypeBinderToUse, - manyToOneBinder, - compositeIdentifierToManyToOneBinder, - simpleValueColumnFetcher, - columnNameForPropertyAndPathFetcher, - collectionHolder - ) - PropertyFromValueCreator propertyFromValueCreator = new PropertyFromValueCreator() - ComponentUpdater componentUpdater = new ComponentUpdater(propertyFromValueCreator) - ComponentBinder componentBinder = new ComponentBinder( - metadataBuildingContext, - binder.getMappingCacheHolder(), - enumTypeBinderToUse, - collectionBinder, - simpleValueBinder, - oneToOneBinder, - manyToOneBinder, - columnNameForPropertyAndPathFetcher, - componentUpdater - ) - - GrailsPropertyBinder propertyBinder = new GrailsPropertyBinder( - metadataBuildingContext, - namingStrategy, - enumTypeBinderToUse, - componentBinder, - collectionBinder, - simpleValueBinder, - columnNameForPropertyAndPathFetcher, - oneToOneBinder, - manyToOneBinder, - propertyFromValueCreator - ) - CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder, componentUpdater, propertyBinder) - PropertyBinder propertyBinderHelper = new PropertyBinder() - SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper) - IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder) - VersionBinder versionBinder = new VersionBinder(metadataBuildingContext, simpleValueBinder, propertyBinderHelper, BasicValue::new) - - ClassBinder classBinder = new ClassBinder() - ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder() - JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder) - UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder) - SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder) - - return [ - propertyBinder: propertyBinder, - collectionBinder: collectionBinder, - identityBinder: identityBinder, - versionBinder: versionBinder, - defaultColumnNameFetcher: defaultColumnNameFetcher, - columnNameForPropertyAndPathFetcher: columnNameForPropertyAndPathFetcher, - classBinder: classBinder, - classPropertiesBinder: classPropertiesBinder, - multiTenantFilterBinder: multiTenantFilterBinder, - joinedSubClassBinder: joinedSubClassBinder, - unionSubclassBinder: unionSubclassBinder, - singleTableSubclassBinder: singleTableSubclassBinder - ] - } - - protected void bindRoot(GrailsDomainBinder binder, GrailsHibernatePersistentEntity entity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { - def binders = getBinders(binder) - binder.bindRoot(entity, mappings, sessionFactoryBeanName, - binders.defaultColumnNameFetcher, - binders.identityBinder as IdentityBinder, - binders.versionBinder as VersionBinder, - binders.classBinder as ClassBinder, - binders.classPropertiesBinder as ClassPropertiesBinder, - binders.multiTenantFilterBinder as MultiTenantFilterBinder, - binders.joinedSubClassBinder as JoinedSubClassBinder, - binders.unionSubclassBinder as UnionSubclassBinder, - binders.singleTableSubclassBinder as SingleTableSubclassBinder) - } - - void setupSpec() { - manager.addAllDomainClasses([ - org.apache.grails.data.testing.tck.domains.Pet, - org.apache.grails.data.testing.tck.domains.Person, - org.apache.grails.data.testing.tck.domains.PetType - ]) - } - - void "Test bind collection"() { - given: - def binder = getGrailsDomainBinder() - def collectionBinder = getBinders(binder).collectionBinder - def collector = getCollector() - - def personEntity = getPersistentEntity(org.apache.grails.data.testing.tck.domains.Person) as GrailsHibernatePersistentEntity - def petEntity = getPersistentEntity(org.apache.grails.data.testing.tck.domains.Pet) as GrailsHibernatePersistentEntity - - def rootClass = new RootClass(binder.getMetadataBuildingContext()) - rootClass.setEntityName(personEntity.name) - rootClass.setTable(collector.addTable(null, null, "PERSON", null, false, binder.getMetadataBuildingContext())) - - def petsProp = personEntity.getPropertyByName("pets") as GrailsHibernatePersistentProperty - - when: - def collection = collectionBinder.bindCollection(petsProp, rootClass, collector, "") - - then: - collection.role == "${personEntity.name}.pets".toString() - collection.element instanceof OneToMany - (collection.element as OneToMany).referencedEntityName == petEntity.name - } -} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreatorSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreatorSpec.groovy new file mode 100644 index 0000000000..6d1a31dd88 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/PrimaryKeyValueCreatorSpec.groovy @@ -0,0 +1,83 @@ +package org.grails.orm.hibernate.cfg.domainbinding.secondpass + +import grails.gorm.specs.HibernateGormDatastoreSpec +import org.hibernate.boot.spi.MetadataBuildingContext +import org.hibernate.mapping.Bag +import org.hibernate.mapping.Collection +import org.hibernate.mapping.DependantValue +import org.hibernate.mapping.KeyValue +import org.hibernate.mapping.PersistentClass +import org.hibernate.mapping.RootClass +import org.hibernate.mapping.Table +import org.hibernate.mapping.SimpleValue +import org.hibernate.mapping.Property +import org.hibernate.mapping.BasicValue +import spock.lang.Subject + +class PrimaryKeyValueCreatorSpec extends HibernateGormDatastoreSpec { + + @Subject + PrimaryKeyValueCreator creator + + MetadataBuildingContext metadataBuildingContext + + def setup() { + metadataBuildingContext = getGrailsDomainBinder().getMetadataBuildingContext() + creator = new PrimaryKeyValueCreator(metadataBuildingContext) + } + + void "test createPrimaryKeyValue with default identifier"() { + given: + Table ownerTable = new Table() + ownerTable.setName("OWNER") + RootClass owner = new RootClass(metadataBuildingContext) + owner.setTable(ownerTable) + + KeyValue identifier = new BasicValue(metadataBuildingContext, ownerTable) + owner.setIdentifier(identifier) + + Table collectionTable = new Table() + collectionTable.setName("COLLECTION") + Collection collection = new Bag(metadataBuildingContext, owner) + collection.setCollectionTable(collectionTable) + collection.setSorted(true) + + when: + DependantValue result = creator.createPrimaryKeyValue(collection) + + then: + result != null + result.getTable().name == "COLLECTION" + result.isSorted() + result.isNullable() + result.isUpdateable() + } + + void "test createPrimaryKeyValue with referenced property"() { + given: + Table ownerTable = new Table() + ownerTable.setName("OWNER") + RootClass owner = new RootClass(metadataBuildingContext) + owner.setTable(ownerTable) + + Property referencedProperty = new Property() + referencedProperty.name = "myProp" + KeyValue propertyValue = new BasicValue(metadataBuildingContext, ownerTable) + referencedProperty.setValue(propertyValue) + owner.addProperty(referencedProperty) + + Table collectionTable = new Table() + collectionTable.setName("COLLECTION") + Collection collection = new Bag(metadataBuildingContext, owner) + collection.setCollectionTable(collectionTable) + collection.setReferencedPropertyName("myProp") + collection.setSorted(false) + + when: + DependantValue result = creator.createPrimaryKeyValue(collection) + + then: + result != null + !result.isSorted() + } +}
