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 d7eb1b369ebfc78919dc6a6714e9542c3432a88c Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Feb 28 13:57:03 2026 -0600 refactor MultiTenantFilterBinder --- .../domainbinding/binder/GrailsDomainBinder.java | 14 ++-- .../cfg/domainbinding/binder/RootBinder.java | 6 +- .../cfg/domainbinding/binder/SubClassBinder.java | 6 +- .../util/MultiTenantFilterBinder.java | 40 ++++-------- .../util/MultiTenantFilterDefinitionBinder.java | 57 +++++++++++++++++ .../cfg/domainbinding/CollectionBinderSpec.groovy | 6 +- .../domainbinding/GrailsPropertyBinderSpec.groovy | 6 +- .../cfg/domainbinding/binder/RootBinderSpec.groovy | 11 +--- .../domainbinding/binder/SubClassBinderSpec.groovy | 8 +-- .../secondpass/ListSecondPassBinderSpec.groovy | 6 +- .../secondpass/MapSecondPassBinderSpec.groovy | 6 +- .../util/MultiTenantFilterBinderSpec.groovy | 15 +++-- .../MultiTenantFilterDefinitionBinderSpec.groovy | 74 ++++++++++++++++++++++ 13 files changed, 181 insertions(+), 74 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 6128ead4c7..cbf3bf98eb 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 @@ -29,6 +29,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndP import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher; import org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver; import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder; +import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder; import org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider; import org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyWrapper; import org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator; @@ -185,7 +186,11 @@ public class GrailsDomainBinder implements AdditionalMappingContributor, TypeCon new ClassPropertiesBinder( grailsPropertyBinder, propertyFromValueCreator, naturalIdentifierBinder); MultiTenantFilterBinder multiTenantFilterBinder = - new MultiTenantFilterBinder(new GrailsPropertyResolver()); + new MultiTenantFilterBinder( + new GrailsPropertyResolver(), + new MultiTenantFilterDefinitionBinder(), + metadataCollector, + defaultColumnNameFetcher); JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder( metadataBuildingContext, @@ -207,11 +212,7 @@ public class GrailsDomainBinder implements AdditionalMappingContributor, TypeCon classPropertiesBinder); SubClassBinder subClassBinder = new SubClassBinder( - mappingCacheHolder, - subclassMappingBinder, - multiTenantFilterBinder, - defaultColumnNameFetcher, - dataSourceName); + mappingCacheHolder, subclassMappingBinder, multiTenantFilterBinder, dataSourceName); RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder( metadataBuildingContext, @@ -232,7 +233,6 @@ public class GrailsDomainBinder implements AdditionalMappingContributor, TypeCon dataSourceName, multiTenantFilterBinder, subClassBinder, - defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinder.java index 07a401bc82..7d45d5a207 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinder.java @@ -38,7 +38,6 @@ public class RootBinder { private final String dataSourceName; private final MultiTenantFilterBinder multiTenantFilterBinder; private final SubClassBinder subClassBinder; - private final DefaultColumnNameFetcher defaultColumnNameFetcher; private final RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder; private final DiscriminatorPropertyBinder discriminatorPropertyBinder; @@ -46,13 +45,11 @@ public class RootBinder { String dataSourceName, MultiTenantFilterBinder multiTenantFilterBinder, SubClassBinder subClassBinder, - DefaultColumnNameFetcher defaultColumnNameFetcher, RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder, DiscriminatorPropertyBinder discriminatorPropertyBinder) { this.dataSourceName = dataSourceName; this.multiTenantFilterBinder = multiTenantFilterBinder; this.subClassBinder = subClassBinder; - this.defaultColumnNameFetcher = defaultColumnNameFetcher; this.rootPersistentClassCommonValuesBinder = rootPersistentClassCommonValuesBinder; this.discriminatorPropertyBinder = discriminatorPropertyBinder; } @@ -86,8 +83,7 @@ public class RootBinder { // bind the sub classes children.forEach(sub -> subClassBinder.bindSubClass(sub, root, mappings, m)); - multiTenantFilterBinder.addMultiTenantFilterIfNecessary( - entity, root, mappings, defaultColumnNameFetcher); + multiTenantFilterBinder.addMultiTenantFilterIfNecessary(entity, root); mappings.addEntityBinding(root); } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java index 768a14d32f..8b416c6bd9 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java @@ -35,19 +35,16 @@ public class SubClassBinder { private final MappingCacheHolder mappingCacheHolder; private final SubclassMappingBinder subclassMappingBinder; private final MultiTenantFilterBinder multiTenantFilterBinder; - private final DefaultColumnNameFetcher defaultColumnNameFetcher; private final String dataSourceName; public SubClassBinder( MappingCacheHolder mappingCacheHolder, SubclassMappingBinder subclassMappingBinder, MultiTenantFilterBinder multiTenantFilterBinder, - DefaultColumnNameFetcher defaultColumnNameFetcher, String dataSourceName) { this.mappingCacheHolder = mappingCacheHolder; this.subclassMappingBinder = subclassMappingBinder; this.multiTenantFilterBinder = multiTenantFilterBinder; - this.defaultColumnNameFetcher = defaultColumnNameFetcher; this.dataSourceName = dataSourceName; } @@ -70,8 +67,7 @@ public class SubClassBinder { parent.addSubclass(subClass); mappings.addEntityBinding(subClass); - multiTenantFilterBinder.addMultiTenantFilterIfNecessary( - sub, subClass, mappings, defaultColumnNameFetcher); + multiTenantFilterBinder.addMultiTenantFilterIfNecessary(sub, subClass); Collection<GrailsHibernatePersistentEntity> children = sub.getChildEntities(dataSourceName); if (!children.isEmpty()) { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java index f0b7f518ed..412e9c18df 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java @@ -25,12 +25,9 @@ import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.datastore.mapping.model.types.TenantId; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity; import org.hibernate.boot.spi.InFlightMetadataCollector; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.RootClass; -import org.hibernate.metamodel.mapping.JdbcMapping; /** * Utility class for binding multi-tenant filters to the Hibernate meta model. @@ -40,9 +37,19 @@ import org.hibernate.metamodel.mapping.JdbcMapping; public class MultiTenantFilterBinder { private final GrailsPropertyResolver grailsPropertyResolver; + private final MultiTenantFilterDefinitionBinder filterDefinitionBinder; + private final InFlightMetadataCollector mappings; + private final DefaultColumnNameFetcher fetcher; - public MultiTenantFilterBinder(GrailsPropertyResolver grailsPropertyResolver) { + public MultiTenantFilterBinder( + @Nonnull GrailsPropertyResolver grailsPropertyResolver, + @Nonnull MultiTenantFilterDefinitionBinder filterDefinitionBinder, + @Nonnull InFlightMetadataCollector mappings, + @Nonnull DefaultColumnNameFetcher fetcher) { this.grailsPropertyResolver = grailsPropertyResolver; + this.filterDefinitionBinder = filterDefinitionBinder; + this.mappings = mappings; + this.fetcher = fetcher; } /** @@ -50,14 +57,9 @@ public class MultiTenantFilterBinder { * * @param entity The target persistent entity * @param persistentClass The persistent class to add the filter to - * @param mappings The in-flight metadata collector - * @param fetcher The column name fetcher */ public void addMultiTenantFilterIfNecessary( - @Nonnull GrailsHibernatePersistentEntity entity, - @Nonnull PersistentClass persistentClass, - @Nonnull InFlightMetadataCollector mappings, - @Nonnull DefaultColumnNameFetcher fetcher) { + @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull PersistentClass persistentClass) { if (!entity.isMultiTenant()) { return; @@ -69,28 +71,14 @@ public class MultiTenantFilterBinder { .ifPresent( property -> { var filterName = GormProperties.TENANT_IDENTITY; - ensureGlobalFilterDefinition(mappings, filterName, property); - applyFilterToPersistentClass(entity, persistentClass, fetcher, filterName, property); + filterDefinitionBinder.ensureGlobalFilterDefinition(mappings, filterName, property); + applyFilterToPersistentClass(entity, persistentClass, filterName, property); }); } - private void ensureGlobalFilterDefinition( - InFlightMetadataCollector mappings, String filterName, Property property) { - if (mappings.getFilterDefinition(filterName) == null - && property.getValue() instanceof BasicValue basicValue) { - JdbcMapping jdbcMapping = basicValue.resolve().getJdbcMapping(); - mappings.addFilterDefinition( - new FilterDefinition( - filterName, - null, // No default condition; let classes specify their own - Collections.singletonMap(filterName, jdbcMapping))); - } - } - private void applyFilterToPersistentClass( GrailsHibernatePersistentEntity entity, PersistentClass persistentClass, - DefaultColumnNameFetcher fetcher, String filterName, Property property) { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinder.java new file mode 100644 index 0000000000..51d21f8409 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinder.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.grails.orm.hibernate.cfg.domainbinding.util; + +import jakarta.annotation.Nonnull; +import java.util.Collections; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.mapping.BasicValue; +import org.hibernate.mapping.Property; +import org.hibernate.metamodel.mapping.JdbcMapping; + +/** + * Utility class for binding multi-tenant filter definitions to the Hibernate meta model. + * + * @since 7.0 + */ +public class MultiTenantFilterDefinitionBinder { + + /** + * Ensures that a global filter definition exists for the given filter name. + * + * @param mappings The in-flight metadata collector + * @param filterName The name of the filter + * @param property The property to get the type from + */ + public void ensureGlobalFilterDefinition( + @Nonnull InFlightMetadataCollector mappings, + @Nonnull String filterName, + @Nonnull Property property) { + if (mappings.getFilterDefinition(filterName) == null + && property.getValue() instanceof BasicValue basicValue) { + JdbcMapping jdbcMapping = basicValue.resolve().getJdbcMapping(); + mappings.addFilterDefinition( + new FilterDefinition( + filterName, + null, // No default condition; let classes specify their own + Collections.singletonMap(filterName, jdbcMapping))); + } + } +} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy index 88db2b6048..69a2d7be6c 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy @@ -112,16 +112,16 @@ class CollectionBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder() + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) 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) SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder) - SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, defaultColumnNameFetcher, "dataSource") + SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource") RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder) DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, binder.getMappingCacheHolder(), new org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()), new org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.Si [...] - RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) + RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) return [ propertyBinder: propertyBinder, 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 b75fa6a9e7..d42d951f2b 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 @@ -172,16 +172,16 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator, naturalIdentifierBinder) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder() + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) 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) SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder) - SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, defaultColumnNameFetcher, "dataSource") + SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource") RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder) DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, binder.getMappingCacheHolder(), new org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()), new org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.Si [...] - RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) + RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) return [ propertyBinder: propertyBinder, diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy index 587631e269..567ca9b235 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinderSpec.groovy @@ -5,7 +5,6 @@ import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.orm.hibernate.cfg.Mapping import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity -import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder import org.hibernate.boot.spi.MetadataBuildingContext import org.hibernate.mapping.RootClass @@ -15,7 +14,6 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { RootBinder binder MultiTenantFilterBinder multiTenantFilterBinder SubClassBinder subClassBinder - DefaultColumnNameFetcher defaultColumnNameFetcher RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder DiscriminatorPropertyBinder discriminatorPropertyBinder MetadataBuildingContext metadataBuildingContext @@ -28,16 +26,13 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { multiTenantFilterBinder = Mock(MultiTenantFilterBinder) subClassBinder = Mock(SubClassBinder) - defaultColumnNameFetcher = Mock(DefaultColumnNameFetcher) rootPersistentClassCommonValuesBinder = Mock(RootPersistentClassCommonValuesBinder) discriminatorPropertyBinder = Mock(DiscriminatorPropertyBinder) binder = new RootBinder( - "default" - , + "default", multiTenantFilterBinder, subClassBinder, - defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder ) @@ -62,7 +57,7 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { 1 * rootPersistentClassCommonValuesBinder.bindRootPersistentClassCommonValues(entity, [], mappings) >> rootClass 0 * discriminatorPropertyBinder.bindDiscriminatorProperty(_) 0 * subClassBinder.bindSubClass(_, _, _, _) - 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(entity, rootClass, mappings, defaultColumnNameFetcher) + 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(entity, rootClass) mappings.getEntityBinding("Parent") == rootClass } @@ -89,7 +84,7 @@ class RootBinderSpec extends HibernateGormDatastoreSpec { 1 * rootPersistentClassCommonValuesBinder.bindRootPersistentClassCommonValues(entity, [childEntity], mappings) >> rootClass 1 * discriminatorPropertyBinder.bindDiscriminatorProperty(rootClass) 1 * subClassBinder.bindSubClass(childEntity, rootClass, mappings, mapping) - 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(entity, rootClass, mappings, defaultColumnNameFetcher) + 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(entity, rootClass) mappings.getEntityBinding("Parent") == rootClass } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy index 72646b2c22..fd81f6148c 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinderSpec.groovy @@ -5,7 +5,6 @@ import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.orm.hibernate.cfg.Mapping import org.grails.orm.hibernate.cfg.MappingCacheHolder import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity -import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder import org.hibernate.boot.spi.MetadataBuildingContext import org.hibernate.mapping.PersistentClass @@ -18,7 +17,6 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { SubClassBinder binder SubclassMappingBinder subclassMappingBinder MultiTenantFilterBinder multiTenantFilterBinder - DefaultColumnNameFetcher defaultColumnNameFetcher MappingCacheHolder mappingCacheHolder MetadataBuildingContext metadataBuildingContext @@ -29,13 +27,11 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { mappingCacheHolder = gdb.getMappingCacheHolder() subclassMappingBinder = Mock(SubclassMappingBinder) multiTenantFilterBinder = Mock(MultiTenantFilterBinder) - defaultColumnNameFetcher = Mock(DefaultColumnNameFetcher) binder = new SubClassBinder( mappingCacheHolder, subclassMappingBinder, multiTenantFilterBinder, - defaultColumnNameFetcher, "default" ) } @@ -59,7 +55,7 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { then: 1 * subclassMappingBinder.createSubclassMapping(subEntity, rootClass, mappings, mapping) >> subClass - 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(subEntity, subClass, mappings, defaultColumnNameFetcher) + 1 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(subEntity, subClass) rootClass.getSubclasses().contains(subClass) mappings.getEntityBinding(subClass.getEntityName()) == subClass } @@ -92,7 +88,7 @@ class SubClassBinderSpec extends HibernateGormDatastoreSpec { then: 1 * subclassMappingBinder.createSubclassMapping(subEntity, rootClass, mappings, mapping) >> subClass 1 * subclassMappingBinder.createSubclassMapping(grandChildEntity, subClass, mappings, mapping) >> grandChildSubClass - 2 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(_, _, mappings, defaultColumnNameFetcher) + 2 * multiTenantFilterBinder.addMultiTenantFilterIfNecessary(_, _) rootClass.getSubclasses().contains(subClass) subClass.getSubclasses().contains(grandChildSubClass) } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy index f8e24f4e63..50cbd74416 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy @@ -111,16 +111,16 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder() + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) 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) SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder) - SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, defaultColumnNameFetcher, "dataSource") + SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource") RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder) DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, binder.getMappingCacheHolder(), new org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()), new org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.Si [...] - RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) + RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) return [ propertyBinder: propertyBinder, diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy index d54e67f3eb..3c31e59b8a 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy @@ -111,16 +111,16 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder() + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) 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) SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder) - SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, defaultColumnNameFetcher, "dataSource") + SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource") RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder) DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, binder.getMappingCacheHolder(), new org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()), new org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.Si [...] - RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, defaultColumnNameFetcher, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) + RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder) return [ propertyBinder: propertyBinder, diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy index cbe3734905..28008119fe 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy @@ -20,9 +20,14 @@ import org.grails.datastore.mapping.model.types.TenantId class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { GrailsPropertyResolver grailsPropertyResolver = Mock(GrailsPropertyResolver) - MultiTenantFilterBinder filterBinder = new MultiTenantFilterBinder(grailsPropertyResolver) DefaultColumnNameFetcher fetcher = Mock(DefaultColumnNameFetcher) InFlightMetadataCollector mockCollector = GroovyMock(InFlightMetadataCollector) + MultiTenantFilterDefinitionBinder filterDefinitionBinder = new MultiTenantFilterDefinitionBinder() + MultiTenantFilterBinder filterBinder + + void setup() { + filterBinder = new MultiTenantFilterBinder(grailsPropertyResolver, filterDefinitionBinder, mockCollector, fetcher) + } void "test add multi tenant filter to root class"() { given: @@ -53,7 +58,7 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { entity.getMultiTenantFilterCondition(fetcher) >> "tenant_id = :tenantId" when: - filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass, mockCollector, fetcher) + filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass) then: 1 * mockCollector.addFilterDefinition(_ as FilterDefinition) @@ -88,7 +93,7 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { mockCollector.getFilterDefinition(_) >> Mock(FilterDefinition) when: - filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass, mockCollector, fetcher) + filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass) then: !persistentClass.getFilters().any { it.getName() == GormProperties.TENANT_IDENTITY } @@ -125,7 +130,7 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { mockCollector.getFilterDefinition(_) >> Mock(FilterDefinition) when: - filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass, mockCollector, fetcher) + filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass) then: !persistentClass.getFilters().any { it.getName() == GormProperties.TENANT_IDENTITY } @@ -160,7 +165,7 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { entity.getMultiTenantFilterCondition(fetcher) >> "tenant_id = :tenantId" when: - filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass, mockCollector, fetcher) + filterBinder.addMultiTenantFilterIfNecessary(entity, persistentClass) then: persistentClass.getFilters().any { it.getName() == GormProperties.TENANT_IDENTITY && it.getCondition() == "tenant_id = :tenantId" } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinderSpec.groovy new file mode 100644 index 0000000000..9703553b27 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterDefinitionBinderSpec.groovy @@ -0,0 +1,74 @@ +package org.grails.orm.hibernate.cfg.domainbinding.util + +import grails.gorm.specs.HibernateGormDatastoreSpec +import org.grails.datastore.mapping.model.config.GormProperties +import org.hibernate.boot.spi.InFlightMetadataCollector +import org.hibernate.mapping.BasicValue +import org.hibernate.mapping.Property +import org.hibernate.mapping.Table +import org.hibernate.engine.spi.FilterDefinition +import org.hibernate.metamodel.mapping.JdbcMapping + +/** + * Tests for MultiTenantFilterDefinitionBinder. + */ +class MultiTenantFilterDefinitionBinderSpec extends HibernateGormDatastoreSpec { + + MultiTenantFilterDefinitionBinder filterDefinitionBinder = new MultiTenantFilterDefinitionBinder() + InFlightMetadataCollector mockCollector = GroovyMock(InFlightMetadataCollector) + + void "test ensureGlobalFilterDefinition adds filter definition if not present"() { + given: + def buildingContext = getGrailsDomainBinder().getMetadataBuildingContext() + def property = new Property() + property.setName("tenantId") + + def table = new Table("ROOT_TABLE") + def value = new BasicValue(buildingContext, table) + value.setTypeName("long") + property.setValue(value) + + def filterName = GormProperties.TENANT_IDENTITY + + when: + filterDefinitionBinder.ensureGlobalFilterDefinition(mockCollector, filterName, property) + + then: + 1 * mockCollector.getFilterDefinition(filterName) >> null + 1 * mockCollector.addFilterDefinition({ FilterDefinition fd -> + fd.getFilterName() == filterName && + fd.getDefaultFilterCondition() == null && + fd.getParameterNames().contains(filterName) + }) + } + + void "test ensureGlobalFilterDefinition does not add if already present"() { + given: + def property = new Property() + def filterName = GormProperties.TENANT_IDENTITY + def existingFilter = Mock(FilterDefinition) + + when: + filterDefinitionBinder.ensureGlobalFilterDefinition(mockCollector, filterName, property) + + then: + 1 * mockCollector.getFilterDefinition(filterName) >> existingFilter + 0 * mockCollector.addFilterDefinition(_) + } + + void "test ensureGlobalFilterDefinition does not add if property value is not BasicValue"() { + given: + def property = new Property() + def filterName = GormProperties.TENANT_IDENTITY + + // Property with no value (null) + property.setValue(null) + + when: + filterDefinitionBinder.ensureGlobalFilterDefinition(mockCollector, filterName, property) + + then: + 1 * mockCollector.getFilterDefinition(filterName) >> null + 0 * mockCollector.addFilterDefinition(_) + } +}
