diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
index c64d98d3ae..2c7ec3ee1f 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
@@ -92,10 +92,12 @@ import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.InFlightMetadataCollector.EntityTableXref;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
+import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.FkSecondPass;
import org.hibernate.cfg.SecondPass;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
+import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.id.PersistentIdentifierGenerator;
@@ -104,6 +106,7 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
+import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Any;
import org.hibernate.mapping.Array;
@@ -3460,18 +3463,25 @@ public class ModelBinder {
final PersistentClass referencedEntityBinding = mappingDocument.getMetadataCollector()
.getEntityBinding( elementSource.getReferencedEntityName() );
- // For a one-to-many association, there are 2 possible sources of "where" clauses that apply
- // to the associated entity table:
- // 1) from the associated entity mapping; i.e.,
- // 2) from the collection mapping; e.g.,
- // Collection#setWhere is used to set the "where" clause that applies to the collection table
- // (which is the associated entity table for a one-to-many association).
- collectionBinding.setWhere(
- StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
- referencedEntityBinding.getWhere(),
- getPluralAttributeSource().getWhere()
- )
- );
+
+ if ( useEntityWhereClauseForCollections() ) {
+ // For a one-to-many association, there are 2 possible sources of "where" clauses that apply
+ // to the associated entity table:
+ // 1) from the associated entity mapping; i.e.,
+ // 2) from the collection mapping; e.g.,
+ // Collection#setWhere is used to set the "where" clause that applies to the collection table
+ // (which is the associated entity table for a one-to-many association).
+ collectionBinding.setWhere(
+ StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
+ referencedEntityBinding.getWhere(),
+ getPluralAttributeSource().getWhere()
+ )
+ );
+ }
+ else {
+ // ignore entity's where clause
+ collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
+ }
elementBinding.setReferencedEntityName( referencedEntityBinding.getEntityName() );
elementBinding.setAssociatedClass( referencedEntityBinding );
@@ -3531,18 +3541,26 @@ public class ModelBinder {
// (which is the join table for a many-to-many association).
// This "where" clause comes from the collection mapping; e.g.,
getCollectionBinding().setWhere( getPluralAttributeSource().getWhere() );
- // For a many-to-many association, there are 2 possible sources of "where" clauses that apply
- // to the associated entity table (not the join table):
- // 1) from the associated entity mapping; i.e.,
- // 2) from the many-to-many mapping; i.e
- // Collection#setManytoManyWhere is used to set the "where" clause that applies to
- // to the many-to-many associated entity table (not the join table).
- getCollectionBinding().setManyToManyWhere(
- StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
- referencedEntityBinding.getWhere(),
- elementSource.getWhere()
- )
- );
+
+ if ( useEntityWhereClauseForCollections() ) {
+ // For a many-to-many association, there are 2 possible sources of "where" clauses that apply
+ // to the associated entity table (not the join table):
+ // 1) from the associated entity mapping; i.e.,
+ // 2) from the many-to-many mapping; i.e
+ // Collection#setManytoManyWhere is used to set the "where" clause that applies to
+ // to the many-to-many associated entity table (not the join table).
+ getCollectionBinding().setManyToManyWhere(
+ StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty(
+ referencedEntityBinding.getWhere(),
+ elementSource.getWhere()
+ )
+ );
+ }
+ else {
+ // ignore entity's where clause
+ getCollectionBinding().setManyToManyWhere( elementSource.getWhere() );
+ }
+
getCollectionBinding().setManyToManyOrdering( elementSource.getOrder() );
if ( !CollectionHelper.isEmpty( elementSource.getFilterSources() )
@@ -3624,6 +3642,18 @@ public class ModelBinder {
}
}
+ private boolean useEntityWhereClauseForCollections() {
+ return ConfigurationHelper.getBoolean(
+ AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS,
+ metadataBuildingContext
+ .getBuildingOptions()
+ .getServiceRegistry()
+ .getService( ConfigurationService.class )
+ .getSettings(),
+ true
+ );
+ }
+
private class PluralAttributeListSecondPass extends AbstractPluralAttributeSecondPass {
public PluralAttributeListSecondPass(
MappingDocument sourceDocument,
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
index 4d2712bccf..e8634f160f 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
@@ -1480,6 +1480,22 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
*/
String CUSTOM_ENTITY_DIRTINESS_STRATEGY = "hibernate.entity_dirtiness_strategy";
+ /**
+ * Controls whether an entity's "where" clause, mapped using @Where(clause="....")
+ * or <entity ... where="...">
, is taken into account when loading one-to-many
+ * or many-to-many collections of that type of entity.
+ *
+ * This setting has no affect on collections of embeddable values containing an association to
+ * that type of entity.
+ *
+ * When `true` (the default), the entity's "where" clause will be taken into account when loading
+ * one-to-many or many-to-many collections of that type of entity.
+ *
+ * `false` indicates that the entity's "where" clause will be ignored when loading one-to-many or
+ * many-to-many collections of that type of entity.
+ */
+ String USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS = "hibernate.use_entity_where_clause_for_collections";
+
/**
* Strategy for multi-tenancy.
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
index dbeeea5ba4..554c13cfc0 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
@@ -70,6 +70,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotationBinder;
+import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.CollectionPropertyHolder;
import org.hibernate.cfg.CollectionSecondPass;
@@ -84,9 +85,11 @@ import org.hibernate.cfg.PropertyInferredData;
import org.hibernate.cfg.PropertyPreloadedData;
import org.hibernate.cfg.SecondPass;
import org.hibernate.criterion.Junction;
+import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
+import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.mapping.Any;
import org.hibernate.mapping.Backref;
import org.hibernate.mapping.Collection;
@@ -953,13 +956,24 @@ public abstract class CollectionBinder {
}
}
+ final boolean useEntityWhereClauseForCollections = ConfigurationHelper.getBoolean(
+ AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS,
+ buildingContext
+ .getBuildingOptions()
+ .getServiceRegistry()
+ .getService( ConfigurationService.class )
+ .getSettings(),
+ true
+ );
+
// There are 2 possible sources of "where" clauses that apply to the associated entity table:
// 1) from the associated entity mapping; i.e., @Entity @Where(clause="...")
+ // (ignored if useEntityWhereClauseForCollections == false)
// 2) from the collection mapping;
// for one-to-many, e.g., @OneToMany @JoinColumn @Where(clause="...") public Set getRatings();
// for many-to-many e.g., @ManyToMany @Where(clause="...") public Set getRatings();
String whereOnClassClause = null;
- if ( property.getElementClass() != null ) {
+ if ( useEntityWhereClauseForCollections && property.getElementClass() != null ) {
Where whereOnClass = property.getElementClass().getAnnotation( Where.class );
if ( whereOnClass != null ) {
whereOnClassClause = whereOnClass.clause();