HHH-13011 : Add option enabling/disabling use of an entity's mapped where-clause when loading collections of that entity
This commit is contained in:
parent
19dd186d11
commit
4735c2d5aa
|
@ -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., <class name="..." ... where="..." .../>
|
||||
// 2) from the collection mapping; e.g., <set name="..." ... where="..." .../>
|
||||
// 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., <class name="..." ... where="..." .../>
|
||||
// 2) from the collection mapping; e.g., <set name="..." ... where="..." .../>
|
||||
// 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., <set name="..." ... where="..." .../>
|
||||
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., <class name="..." ... where="..." .../>
|
||||
// 2) from the many-to-many mapping; i.e <many-to-many ... where="...".../>
|
||||
// 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., <class name="..." ... where="..." .../>
|
||||
// 2) from the many-to-many mapping; i.e <many-to-many ... where="...".../>
|
||||
// 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,
|
||||
|
|
|
@ -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 <code>@Where(clause="....")</code>
|
||||
* or <code><entity ... where="..."></code>, is taken into account when loading one-to-many
|
||||
* or many-to-many collections of that type of entity.
|
||||
* <p/>
|
||||
* This setting has no affect on collections of embeddable values containing an association to
|
||||
* that type of entity.
|
||||
* <p/>
|
||||
* 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.
|
||||
* <p/>
|
||||
* `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.
|
||||
|
||||
|
|
|
@ -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<Rating> getRatings();
|
||||
// for many-to-many e.g., @ManyToMany @Where(clause="...") public Set<Rating> 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();
|
||||
|
|
Loading…
Reference in New Issue