HHH-13769: Avoid unnecessary joins
better support for lazy TableReference handling for collections
This commit is contained in:
parent
becbaea172
commit
dcbef8705c
|
@ -6,11 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,6 +62,4 @@ public interface CollectionPart extends ModelPart, Fetchable {
|
||||||
default String getPartName() {
|
default String getPartName() {
|
||||||
return getNature().getName();
|
return getNature().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPrimaryTableReference(TableGroupBuilder tableGroupBuilder, SqlExpressionResolver sqlExpressionResolver, SqlAstCreationContext creationContext);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,21 +19,17 @@ import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
|
||||||
import org.hibernate.sql.results.ResultsLogger;
|
import org.hibernate.sql.results.ResultsLogger;
|
||||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
|
||||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -78,14 +74,6 @@ public class BasicValuedCollectionPart implements CollectionPart, BasicValuedMod
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryTableReference(
|
|
||||||
TableGroupBuilder tableGroupBuilder,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getContainingTableExpression() {
|
public String getContainingTableExpression() {
|
||||||
return tableExpression;
|
return tableExpression;
|
||||||
|
|
|
@ -23,13 +23,12 @@ import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
|
||||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -78,14 +77,6 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryTableReference(
|
|
||||||
TableGroupBuilder tableGroupBuilder,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcMapping getJdbcMapping() {
|
public JdbcMapping getJdbcMapping() {
|
||||||
return type;
|
return type;
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
||||||
|
@ -198,13 +197,6 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryTableReference(
|
|
||||||
TableGroupBuilder tableGroupBuilder,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReference createPrimaryTableReference(
|
public TableReference createPrimaryTableReference(
|
||||||
SqlAliasBase sqlAliasBase,
|
SqlAliasBase sqlAliasBase,
|
||||||
|
|
|
@ -10,22 +10,16 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
@ -42,7 +36,6 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
||||||
private final Nature nature;
|
private final Nature nature;
|
||||||
private final EntityMappingType entityMappingType;
|
private final EntityMappingType entityMappingType;
|
||||||
|
|
||||||
private ForeignKeyDescriptor foreignKeyDescriptor;
|
|
||||||
private ModelPart fkTargetModelPart;
|
private ModelPart fkTargetModelPart;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
@ -50,24 +43,20 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
||||||
Nature nature,
|
Nature nature,
|
||||||
Value bootModelValue,
|
Value bootModelValue,
|
||||||
EntityMappingType entityMappingType,
|
EntityMappingType entityMappingType,
|
||||||
String fkTargetModelPartName,
|
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
this.nature = nature;
|
this.nature = nature;
|
||||||
this.entityMappingType = entityMappingType;
|
this.entityMappingType = entityMappingType;
|
||||||
|
|
||||||
creationProcess.registerInitializationCallback(
|
|
||||||
() -> {
|
|
||||||
fkTargetModelPart = fkTargetModelPartName == null
|
|
||||||
? entityMappingType.getIdentifierMapping()
|
|
||||||
: entityMappingType.findSubPart( fkTargetModelPartName, entityMappingType );
|
|
||||||
assert fkTargetModelPart != null;
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
public void finishInitialization(
|
||||||
|
CollectionPersister collectionDescriptor,
|
||||||
|
Collection bootValueMapping,
|
||||||
|
String fkTargetModelPartName,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
fkTargetModelPart = entityMappingType.findSubPart( fkTargetModelPartName, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Nature getNature() {
|
public Nature getNature() {
|
||||||
return nature;
|
return nature;
|
||||||
|
@ -78,24 +67,6 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa
|
||||||
return getEntityMappingType();
|
return getEntityMappingType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryTableReference(
|
|
||||||
TableGroupBuilder tableGroupBuilder,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
tableGroupBuilder.applySecondaryTableReferences(
|
|
||||||
getEntityMappingType().createPrimaryTableReference( tableGroupBuilder.getSqlAliasBase(), sqlExpressionResolver, creationContext ),
|
|
||||||
SqlAstJoinType.LEFT,
|
|
||||||
(lhs, rhs, sqlAstJoinType) -> foreignKeyDescriptor.generateJoinPredicate(
|
|
||||||
lhs,
|
|
||||||
rhs,
|
|
||||||
sqlAstJoinType,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityMappingType getEntityMappingType() {
|
public EntityMappingType getEntityMappingType() {
|
||||||
return entityMappingType;
|
return entityMappingType;
|
||||||
|
|
|
@ -719,6 +719,7 @@ public class MappingModelCreationHelper {
|
||||||
dialect,
|
dialect,
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
final CollectionPart indexDescriptor;
|
final CollectionPart indexDescriptor;
|
||||||
CollectionIdentifierDescriptor identifierDescriptor = null;
|
CollectionIdentifierDescriptor identifierDescriptor = null;
|
||||||
|
|
||||||
|
@ -882,7 +883,7 @@ public class MappingModelCreationHelper {
|
||||||
sessionFactory
|
sessionFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
return new PluralAttributeMappingImpl(
|
final PluralAttributeMappingImpl pluralAttributeMapping = new PluralAttributeMappingImpl(
|
||||||
attrName,
|
attrName,
|
||||||
bootValueMapping,
|
bootValueMapping,
|
||||||
propertyAccess,
|
propertyAccess,
|
||||||
|
@ -905,6 +906,22 @@ public class MappingModelCreationHelper {
|
||||||
declaringType,
|
declaringType,
|
||||||
collectionDescriptor
|
collectionDescriptor
|
||||||
);
|
);
|
||||||
|
creationProcess.registerInitializationCallback(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
pluralAttributeMapping.finishInitialization( bootProperty, bootValueMapping, creationProcess );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (NotYetImplementedFor6Exception nye) {
|
||||||
|
throw nye;
|
||||||
|
}
|
||||||
|
catch (Exception wait) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return pluralAttributeMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ForeignKeyDescriptor interpretKeyDescriptor(
|
private static ForeignKeyDescriptor interpretKeyDescriptor(
|
||||||
|
@ -1095,29 +1112,38 @@ public class MappingModelCreationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bootMapKeyDescriptor instanceof OneToMany || bootMapKeyDescriptor instanceof ToOne ) {
|
if ( bootMapKeyDescriptor instanceof OneToMany || bootMapKeyDescriptor instanceof ToOne ) {
|
||||||
final EntityPersister associatedEntity;
|
|
||||||
|
|
||||||
if ( bootMapKeyDescriptor instanceof OneToMany ) {
|
|
||||||
associatedEntity = creationProcess.getEntityPersister(
|
|
||||||
( (OneToMany) bootMapKeyDescriptor ).getReferencedEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// many-to-many
|
|
||||||
associatedEntity = creationProcess.getEntityPersister(
|
|
||||||
( (ToOne) bootMapKeyDescriptor ).getReferencedEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final EntityType indexEntityType = (EntityType) collectionDescriptor.getIndexType();
|
final EntityType indexEntityType = (EntityType) collectionDescriptor.getIndexType();
|
||||||
|
final EntityPersister associatedEntity = creationProcess.getEntityPersister( indexEntityType.getAssociatedEntityName() );
|
||||||
|
|
||||||
return new EntityCollectionPart(
|
final EntityCollectionPart indexDescriptor = new EntityCollectionPart(
|
||||||
CollectionPart.Nature.ELEMENT,
|
CollectionPart.Nature.INDEX,
|
||||||
bootValueMapping.getElement(),
|
bootMapKeyDescriptor,
|
||||||
associatedEntity,
|
associatedEntity,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
|
||||||
|
creationProcess.registerInitializationCallback(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
indexDescriptor.finishInitialization(
|
||||||
|
collectionDescriptor,
|
||||||
|
bootValueMapping,
|
||||||
indexEntityType.getRHSUniqueKeyPropertyName(),
|
indexEntityType.getRHSUniqueKeyPropertyName(),
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (NotYetImplementedFor6Exception nye) {
|
||||||
|
throw nye;
|
||||||
|
}
|
||||||
|
catch (Exception wait) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return indexDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotYetImplementedFor6Exception(
|
throw new NotYetImplementedFor6Exception(
|
||||||
|
@ -1176,29 +1202,38 @@ public class MappingModelCreationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( element instanceof OneToMany || element instanceof ToOne ) {
|
if ( element instanceof OneToMany || element instanceof ToOne ) {
|
||||||
final EntityPersister associatedEntity;
|
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
|
||||||
|
final EntityPersister associatedEntity = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
|
||||||
|
|
||||||
if ( element instanceof OneToMany ) {
|
final EntityCollectionPart elementDescriptor = new EntityCollectionPart(
|
||||||
associatedEntity = creationProcess.getEntityPersister(
|
|
||||||
( (OneToMany) element ).getReferencedEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// many-to-many
|
|
||||||
associatedEntity = creationProcess.getEntityPersister(
|
|
||||||
( (ToOne) element ).getReferencedEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final EntityType indexEntityType = (EntityType) collectionDescriptor.getElementType();
|
|
||||||
|
|
||||||
return new EntityCollectionPart(
|
|
||||||
CollectionPart.Nature.ELEMENT,
|
CollectionPart.Nature.ELEMENT,
|
||||||
bootDescriptor.getElement(),
|
bootDescriptor.getElement(),
|
||||||
associatedEntity,
|
associatedEntity,
|
||||||
indexEntityType.getRHSUniqueKeyPropertyName(),
|
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
|
creationProcess.registerInitializationCallback(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
elementDescriptor.finishInitialization(
|
||||||
|
collectionDescriptor,
|
||||||
|
bootDescriptor,
|
||||||
|
elementEntityType.getRHSUniqueKeyPropertyName(),
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (NotYetImplementedFor6Exception nye) {
|
||||||
|
throw nye;
|
||||||
|
}
|
||||||
|
catch (Exception wait) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return elementDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotYetImplementedFor6Exception(
|
throw new NotYetImplementedFor6Exception(
|
||||||
|
|
|
@ -82,6 +82,11 @@ public class MappingModelCreationProcess {
|
||||||
postInitCallbacks.remove( callback );
|
postInitCallbacks.remove( callback );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( copy.size() == postInitCallbacks.size() ) {
|
||||||
|
// none of the processes could complete fully, this is an error
|
||||||
|
throw new IllegalStateException( "No post-init callbacks could complete" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,22 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
|
import org.hibernate.mapping.IndexedCollection;
|
||||||
import org.hibernate.mapping.List;
|
import org.hibernate.mapping.List;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.mapping.Value;
|
||||||
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
|
@ -26,6 +32,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
@ -36,8 +43,8 @@ import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
||||||
|
@ -50,11 +57,14 @@ import org.hibernate.sql.results.graph.FetchParent;
|
||||||
import org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult;
|
import org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult;
|
||||||
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
|
import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch;
|
||||||
import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
|
import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
|
import org.hibernate.type.ForeignKeyDirection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class PluralAttributeMappingImpl extends AbstractAttributeMapping implements PluralAttributeMapping {
|
public class PluralAttributeMappingImpl extends AbstractAttributeMapping implements PluralAttributeMapping {
|
||||||
|
|
||||||
public interface Aware {
|
public interface Aware {
|
||||||
void injectAttributeMapping(PluralAttributeMapping attributeMapping);
|
void injectAttributeMapping(PluralAttributeMapping attributeMapping);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +88,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
|
|
||||||
private final IndexMetadata indexMetadata;
|
private final IndexMetadata indexMetadata;
|
||||||
|
|
||||||
|
private ForeignKeyDescriptor manyToManyFkDescriptor;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public PluralAttributeMappingImpl(
|
public PluralAttributeMappingImpl(
|
||||||
String attributeName,
|
String attributeName,
|
||||||
|
@ -152,6 +164,56 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void finishInitialization(
|
||||||
|
Property bootProperty,
|
||||||
|
Collection bootDescriptor,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
if ( collectionDescriptor.getElementType() instanceof EntityType
|
||||||
|
|| collectionDescriptor.getIndexType() instanceof EntityType ) {
|
||||||
|
|
||||||
|
final EntityPersister associatedEntityDescriptor;
|
||||||
|
final ModelPart fkTargetPart;
|
||||||
|
final Value fkBootDescriptorSource;
|
||||||
|
if ( collectionDescriptor.getElementType() instanceof EntityType ) {
|
||||||
|
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
|
||||||
|
associatedEntityDescriptor = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
|
||||||
|
fkTargetPart = elementEntityType.isReferenceToPrimaryKey()
|
||||||
|
? associatedEntityDescriptor.getIdentifierMapping()
|
||||||
|
: associatedEntityDescriptor.findSubPart( elementEntityType.getRHSUniqueKeyPropertyName() );
|
||||||
|
fkBootDescriptorSource = bootDescriptor.getElement();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert collectionDescriptor.getIndexType() != null;
|
||||||
|
assert bootDescriptor instanceof IndexedCollection;
|
||||||
|
|
||||||
|
final EntityType indexEntityType = (EntityType) collectionDescriptor.getIndexType();
|
||||||
|
associatedEntityDescriptor = creationProcess.getEntityPersister( indexEntityType.getAssociatedEntityName() );
|
||||||
|
fkTargetPart = indexEntityType.isReferenceToPrimaryKey()
|
||||||
|
? associatedEntityDescriptor.getIdentifierMapping()
|
||||||
|
: associatedEntityDescriptor.findSubPart( indexEntityType.getRHSUniqueKeyPropertyName() );
|
||||||
|
fkBootDescriptorSource = ( (IndexedCollection) bootDescriptor ).getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fkTargetPart instanceof BasicValuedModelPart ) {
|
||||||
|
final BasicValuedModelPart basicFkTargetPart = (BasicValuedModelPart) fkTargetPart;
|
||||||
|
final Joinable collectionDescriptorAsJoinable = (Joinable) collectionDescriptor;
|
||||||
|
manyToManyFkDescriptor = new SimpleForeignKeyDescriptor(
|
||||||
|
ForeignKeyDirection.TO_PARENT,
|
||||||
|
collectionDescriptorAsJoinable.getTableName(),
|
||||||
|
fkBootDescriptorSource.getColumnIterator().next().getText(),
|
||||||
|
basicFkTargetPart.getContainingTableExpression(),
|
||||||
|
basicFkTargetPart.getMappedColumnExpression(),
|
||||||
|
basicFkTargetPart.getJdbcMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new NotYetImplementedFor6Exception(
|
||||||
|
"Support for composite foreign keys not yet implemented : " + collectionDescriptor.getRole()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CollectionMappingType getMappedTypeDescriptor() {
|
public CollectionMappingType getMappedTypeDescriptor() {
|
||||||
return (CollectionMappingType) super.getMappedTypeDescriptor();
|
return (CollectionMappingType) super.getMappedTypeDescriptor();
|
||||||
|
@ -301,41 +363,51 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
|
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
|
if ( collectionDescriptor.isOneToMany() ) {
|
||||||
|
return createOneToManyTableGroupJoin(
|
||||||
final TableGroupBuilder tableGroupBuilder = TableGroupBuilder.builder(
|
|
||||||
navigablePath,
|
navigablePath,
|
||||||
this,
|
lhs,
|
||||||
|
explicitSourceAlias,
|
||||||
|
sqlAstJoinType,
|
||||||
lockMode,
|
lockMode,
|
||||||
sqlAliasBase,
|
aliasBaseGenerator,
|
||||||
(tableExpression, tableGroup) -> createTableReferenceJoin(
|
|
||||||
tableExpression,
|
|
||||||
sqlAliasBase,
|
|
||||||
tableGroup.getPrimaryTableReference(),
|
|
||||||
sqlAstJoinType == SqlAstJoinType.INNER && ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
),
|
|
||||||
creationContext.getSessionFactory()
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
tableGroupBuilder.applyPrimaryReference(
|
else {
|
||||||
// returns null when there is no "collection table"
|
return createCollectionTableGroupJoin(
|
||||||
getCollectionDescriptor().createPrimaryTableReference(
|
navigablePath,
|
||||||
sqlAliasBase,
|
lhs,
|
||||||
|
explicitSourceAlias,
|
||||||
|
sqlAstJoinType,
|
||||||
|
lockMode,
|
||||||
|
aliasBaseGenerator,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
elementDescriptor.applyPrimaryTableReference(
|
}
|
||||||
tableGroupBuilder,
|
private TableGroupJoin createOneToManyTableGroupJoin(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup lhs,
|
||||||
|
String explicitSourceAlias,
|
||||||
|
SqlAstJoinType sqlAstJoinType,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final TableGroup tableGroup = createOneToManyTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
sqlAstJoinType == SqlAstJoinType.INNER
|
||||||
|
&& ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
|
lockMode,
|
||||||
|
aliasBaseGenerator,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
|
||||||
final TableGroup tableGroup = tableGroupBuilder.build();
|
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
|
@ -354,19 +426,188 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
return tableGroupJoin;
|
return tableGroupJoin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TableGroup createOneToManyTableGroup(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
boolean canUseInnerJoins,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final EntityCollectionPart entityPartDescriptor;
|
||||||
|
if ( elementDescriptor instanceof EntityCollectionPart ) {
|
||||||
|
entityPartDescriptor = (EntityCollectionPart) elementDescriptor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert indexDescriptor instanceof EntityCollectionPart;
|
||||||
|
entityPartDescriptor = (EntityCollectionPart) indexDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||||
|
|
||||||
|
final TableReference primaryTableReference = entityPartDescriptor.getEntityMappingType().createPrimaryTableReference(
|
||||||
|
sqlAliasBase,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
return new StandardTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
this,
|
||||||
|
lockMode,
|
||||||
|
primaryTableReference,
|
||||||
|
sqlAliasBase,
|
||||||
|
(tableExpression, tg) -> createTableReferenceJoin(
|
||||||
|
tableExpression,
|
||||||
|
sqlAliasBase,
|
||||||
|
primaryTableReference,
|
||||||
|
canUseInnerJoins,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
),
|
||||||
|
creationContext.getSessionFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableGroupJoin createCollectionTableGroupJoin(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup lhs,
|
||||||
|
String explicitSourceAlias,
|
||||||
|
SqlAstJoinType sqlAstJoinType,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final TableGroup tableGroup = createCollectionTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
sqlAstJoinType == SqlAstJoinType.INNER
|
||||||
|
&& !getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
|
lockMode,
|
||||||
|
aliasBaseGenerator,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||||
|
navigablePath,
|
||||||
|
sqlAstJoinType,
|
||||||
|
tableGroup,
|
||||||
|
getKeyDescriptor().generateJoinPredicate(
|
||||||
|
lhs,
|
||||||
|
tableGroup,
|
||||||
|
sqlAstJoinType,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
lhs.addTableGroupJoin( tableGroupJoin );
|
||||||
|
|
||||||
|
return tableGroupJoin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableGroup createCollectionTableGroup(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
boolean canUseInnerJoin,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||||
|
|
||||||
|
assert ! getCollectionDescriptor().isOneToMany();
|
||||||
|
|
||||||
|
final String collectionTableName = ( (Joinable) collectionDescriptor ).getTableName();
|
||||||
|
final TableReference collectionTableReference = new TableReference(
|
||||||
|
collectionTableName,
|
||||||
|
sqlAliasBase.generateNewAlias(),
|
||||||
|
true,
|
||||||
|
creationContext.getSessionFactory()
|
||||||
|
);
|
||||||
|
|
||||||
|
final Consumer<TableGroup> tableGroupFinalizer;
|
||||||
|
final BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator;
|
||||||
|
if ( elementDescriptor instanceof EntityCollectionPart || indexDescriptor instanceof EntityCollectionPart ) {
|
||||||
|
final EntityCollectionPart entityPartDescriptor;
|
||||||
|
if ( elementDescriptor instanceof EntityCollectionPart ) {
|
||||||
|
entityPartDescriptor = (EntityCollectionPart) elementDescriptor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entityPartDescriptor = (EntityCollectionPart) indexDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EntityMappingType mappingType = entityPartDescriptor.getEntityMappingType();
|
||||||
|
final TableReference associatedPrimaryTable = mappingType.createPrimaryTableReference(
|
||||||
|
sqlAliasBase,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
tableReferenceJoinCreator = (tableExpression, tableGroup) -> createTableReferenceJoin(
|
||||||
|
tableExpression,
|
||||||
|
sqlAliasBase,
|
||||||
|
associatedPrimaryTable,
|
||||||
|
canUseInnerJoin && ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
tableGroupFinalizer = tableGroup -> {
|
||||||
|
final SqlAstJoinType joinType = canUseInnerJoin && ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable()
|
||||||
|
? SqlAstJoinType.INNER
|
||||||
|
: SqlAstJoinType.LEFT;
|
||||||
|
final TableReferenceJoin associationJoin = new TableReferenceJoin(
|
||||||
|
joinType,
|
||||||
|
associatedPrimaryTable,
|
||||||
|
manyToManyFkDescriptor.generateJoinPredicate(
|
||||||
|
collectionTableReference,
|
||||||
|
associatedPrimaryTable,
|
||||||
|
joinType,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
)
|
||||||
|
);
|
||||||
|
( (StandardTableGroup) tableGroup ).addTableReferenceJoin( associationJoin );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tableReferenceJoinCreator = (tableExpression, tableGroup) -> {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"element-collection cannot contain joins : " + collectionTableReference.getTableExpression() + " -> " + tableExpression
|
||||||
|
);
|
||||||
|
};
|
||||||
|
tableGroupFinalizer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final StandardTableGroup tableGroup = new StandardTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
this,
|
||||||
|
lockMode,
|
||||||
|
collectionTableReference,
|
||||||
|
sqlAliasBase,
|
||||||
|
tableReferenceJoinCreator,
|
||||||
|
creationContext.getSessionFactory()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( tableGroupFinalizer != null ) {
|
||||||
|
tableGroupFinalizer.accept( tableGroup );
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableGroup;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReferenceJoin createTableReferenceJoin(
|
public TableReferenceJoin createTableReferenceJoin(
|
||||||
String joinTableExpression,
|
String joinTableExpression,
|
||||||
SqlAliasBase sqlAliasBase,
|
SqlAliasBase sqlAliasBase,
|
||||||
TableReference lhs,
|
TableReference lhs,
|
||||||
boolean sqlAstJoinType,
|
boolean canUseInnerJoin,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
return getCollectionDescriptor().createTableReferenceJoin(
|
return getCollectionDescriptor().createTableReferenceJoin(
|
||||||
joinTableExpression,
|
joinTableExpression,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
lhs,
|
lhs,
|
||||||
sqlAstJoinType,
|
canUseInnerJoin,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
@ -410,62 +651,26 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
if ( getCollectionDescriptor().isOneToMany() ) {
|
||||||
|
return createOneToManyTableGroup(
|
||||||
final TableGroupBuilder tableGroupBuilder = TableGroupBuilder.builder(
|
|
||||||
navigablePath,
|
navigablePath,
|
||||||
this,
|
canUseInnerJoins,
|
||||||
lockMode,
|
lockMode,
|
||||||
sqlAliasBase,
|
aliasBaseGenerator,
|
||||||
(tableExpression, tableGroup) -> createTableReferenceJoin(
|
|
||||||
tableExpression,
|
|
||||||
sqlAliasBase,
|
|
||||||
tableGroup.getPrimaryTableReference(),
|
|
||||||
canUseInnerJoins && ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
),
|
|
||||||
creationContext.getSessionFactory()
|
|
||||||
);
|
|
||||||
|
|
||||||
getElementDescriptor().applyPrimaryTableReference(
|
|
||||||
tableGroupBuilder,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( getIndexDescriptor() != null ) {
|
|
||||||
getIndexDescriptor().applyPrimaryTableReference(
|
|
||||||
tableGroupBuilder,
|
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
final TableReference collectionTableReference = getCollectionDescriptor().createPrimaryTableReference(
|
return createCollectionTableGroup(
|
||||||
sqlAliasBase,
|
navigablePath,
|
||||||
|
canUseInnerJoins,
|
||||||
|
lockMode,
|
||||||
|
aliasBaseGenerator,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( collectionTableReference != null ) {
|
|
||||||
tableGroupBuilder.applySecondaryTableReferences(
|
|
||||||
collectionTableReference,
|
|
||||||
canUseInnerJoins && ! getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable()
|
|
||||||
? SqlAstJoinType.INNER
|
|
||||||
: SqlAstJoinType.LEFT,
|
|
||||||
(lhs, rhs, sqlAstJoinType) -> fkDescriptor.generateJoinPredicate(
|
|
||||||
lhs,
|
|
||||||
rhs,
|
|
||||||
sqlAstJoinType,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableGroupBuilder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,8 +28,8 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
@ -207,15 +207,22 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
|
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
|
||||||
|
|
||||||
final TableGroupBuilder tableGroupBuilder = TableGroupBuilder.builder(
|
final TableReference primaryTableReference = createPrimaryTableReference(
|
||||||
|
sqlAliasBase,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
final TableGroup tableGroup = new StandardTableGroup(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
this,
|
this,
|
||||||
lockMode,
|
lockMode,
|
||||||
|
primaryTableReference,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
(tableExpression, tableGroup) -> createTableReferenceJoin(
|
(tableExpression, tg) -> createTableReferenceJoin(
|
||||||
tableExpression,
|
tableExpression,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
tableGroup.getPrimaryTableReference(),
|
primaryTableReference,
|
||||||
false,
|
false,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
|
@ -223,25 +230,6 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
creationContext.getSessionFactory()
|
creationContext.getSessionFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
tableGroupBuilder.applyPrimaryReference(
|
|
||||||
getEntityMappingType().createPrimaryTableReference(
|
|
||||||
sqlAliasBase,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// applyTableReferences(
|
|
||||||
// sqlAliasBase,
|
|
||||||
// joinType,
|
|
||||||
// tableGroupBuilder,
|
|
||||||
// sqlExpressionResolver,
|
|
||||||
// creationContext
|
|
||||||
// );
|
|
||||||
|
|
||||||
getMappedTypeDescriptor().getIdentifierMapping();
|
|
||||||
|
|
||||||
final TableGroup tableGroup = tableGroupBuilder.build();
|
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
|
|
|
@ -1882,6 +1882,10 @@ public abstract class AbstractCollectionPersister
|
||||||
return elementPersister;
|
return elementPersister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected EntityPersister getElementPersisterInternal() {
|
||||||
|
return elementPersister;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCollection() {
|
public boolean isCollection() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -2468,65 +2472,6 @@ public abstract class AbstractCollectionPersister
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TableReference createPrimaryTableReference(
|
|
||||||
SqlAliasBase sqlAliasBase,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
if ( qualifiedTableName != null && ! isOneToMany() ) {
|
|
||||||
return new TableReference(
|
|
||||||
qualifiedTableName,
|
|
||||||
sqlAliasBase.generateNewAlias(),
|
|
||||||
false,
|
|
||||||
getFactory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TableReferenceJoin createTableReferenceJoin(
|
|
||||||
String joinTableExpression,
|
|
||||||
SqlAliasBase sqlAliasBase,
|
|
||||||
TableReference lhs,
|
|
||||||
boolean canUseInnerJoin,
|
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
|
||||||
SqlAstCreationContext creationContext) {
|
|
||||||
if ( elementPersister == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String entityPrimaryTableName = ( (Joinable) elementPersister ).getTableName();
|
|
||||||
if ( entityPrimaryTableName.equals( joinTableExpression ) ) {
|
|
||||||
assert qualifiedTableName != null;
|
|
||||||
assert lhs.getTableExpression().equals( qualifiedTableName );
|
|
||||||
|
|
||||||
final TableReference tableReference = elementPersister.createPrimaryTableReference( sqlAliasBase, sqlExpressionResolver, creationContext );
|
|
||||||
final SqlAstJoinType sqlAstJoinType = canUseInnerJoin ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT;
|
|
||||||
return new TableReferenceJoin(
|
|
||||||
sqlAstJoinType,
|
|
||||||
tableReference,
|
|
||||||
generateEntityElementJoinPredicate(
|
|
||||||
lhs,
|
|
||||||
tableReference,
|
|
||||||
sqlAstJoinType,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elementPersister.createTableReferenceJoin(
|
|
||||||
joinTableExpression,
|
|
||||||
sqlAliasBase,
|
|
||||||
lhs,
|
|
||||||
canUseInnerJoin,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTableReferences(
|
public void applyTableReferences(
|
||||||
SqlAliasBase sqlAliasBase,
|
SqlAliasBase sqlAliasBase,
|
||||||
|
@ -2713,10 +2658,6 @@ public abstract class AbstractCollectionPersister
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||||
|
|
||||||
// `lhs` should be the collection table
|
|
||||||
// `rhs` should be the primary element table
|
|
||||||
assert lhs.getTableExpression().equals( getTableName() );
|
|
||||||
|
|
||||||
final String fkTargetModelPartName = getCollectionType().getRHSUniqueKeyPropertyName();
|
final String fkTargetModelPartName = getCollectionType().getRHSUniqueKeyPropertyName();
|
||||||
final ModelPart fkTargetDescriptor;
|
final ModelPart fkTargetDescriptor;
|
||||||
if ( fkTargetModelPartName != null ) {
|
if ( fkTargetModelPartName != null ) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
|
@ -26,6 +27,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.jdbc.Expectation;
|
import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.jdbc.Expectations;
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
|
@ -33,6 +35,12 @@ import org.hibernate.sql.Delete;
|
||||||
import org.hibernate.sql.Insert;
|
import org.hibernate.sql.Insert;
|
||||||
import org.hibernate.sql.SelectFragment;
|
import org.hibernate.sql.SelectFragment;
|
||||||
import org.hibernate.sql.Update;
|
import org.hibernate.sql.Update;
|
||||||
|
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,11 +24,17 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.jdbc.Expectation;
|
import org.hibernate.jdbc.Expectation;
|
||||||
import org.hibernate.jdbc.Expectations;
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.sql.Update;
|
import org.hibernate.sql.Update;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection persister for one-to-many associations.
|
* Collection persister for one-to-many associations.
|
||||||
|
@ -67,6 +73,43 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
||||||
keyIsUpdateable = collectionBinding.getKey().isUpdateable();
|
keyIsUpdateable = collectionBinding.getKey().isUpdateable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference createPrimaryTableReference(
|
||||||
|
SqlAliasBase sqlAliasBase,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
// for a one-to-many, the "primary table" is the primary table of the associated entity
|
||||||
|
final EntityPersister elementPersister = getElementPersister();
|
||||||
|
assert elementPersister != null;
|
||||||
|
|
||||||
|
return elementPersister.createPrimaryTableReference( sqlAliasBase, sqlExpressionResolver, creationContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReferenceJoin createTableReferenceJoin(
|
||||||
|
String joinTableExpression,
|
||||||
|
SqlAliasBase sqlAliasBase,
|
||||||
|
TableReference lhs,
|
||||||
|
boolean canUseInnerJoin,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final EntityPersister elementPersister = getElementPersister();
|
||||||
|
assert elementPersister != null;
|
||||||
|
|
||||||
|
assert qualifiedTableName != null;
|
||||||
|
assert lhs.getTableExpression().equals( qualifiedTableName );
|
||||||
|
assert lhs.getTableExpression().equals( ( (Joinable) elementPersister ).getTableName() );
|
||||||
|
|
||||||
|
return elementPersister.createTableReferenceJoin(
|
||||||
|
joinTableExpression,
|
||||||
|
sqlAliasBase,
|
||||||
|
lhs,
|
||||||
|
canUseInnerJoin,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the SQL UPDATE that updates all the foreign keys to null
|
* Generate the SQL UPDATE that updates all the foreign keys to null
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -181,8 +181,8 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||||
|
@ -1225,10 +1225,17 @@ public abstract class AbstractEntityPersister
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||||
|
|
||||||
final TableGroupBuilder builder = TableGroupBuilder.builder(
|
final TableReference primaryTableReference = createPrimaryTableReference(
|
||||||
|
sqlAliasBase,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
return new StandardTableGroup(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
this,
|
this,
|
||||||
lockMode,
|
lockMode,
|
||||||
|
primaryTableReference,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
(tableExpression, tableGroup) -> {
|
(tableExpression, tableGroup) -> {
|
||||||
for ( int i = 0; i < getSubclassTableSpan(); i++ ) {
|
for ( int i = 0; i < getSubclassTableSpan(); i++ ) {
|
||||||
|
@ -1251,7 +1258,7 @@ public abstract class AbstractEntityPersister
|
||||||
),
|
),
|
||||||
joinedTableReference,
|
joinedTableReference,
|
||||||
generateJoinPredicate(
|
generateJoinPredicate(
|
||||||
tableGroup.getPrimaryTableReference(),
|
primaryTableReference,
|
||||||
joinedTableReference,
|
joinedTableReference,
|
||||||
i,
|
i,
|
||||||
sqlExpressionResolver
|
sqlExpressionResolver
|
||||||
|
@ -1262,27 +1269,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
creationContext.getSessionFactory()
|
getFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
builder.applyPrimaryReference(
|
|
||||||
createPrimaryTableReference(
|
|
||||||
sqlAliasBase,
|
|
||||||
sqlExpressionResolver,
|
|
||||||
creationContext
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// applyTableReferences(
|
|
||||||
// sqlAliasBase,
|
|
||||||
// tableReferenceJoinType,
|
|
||||||
// builder,
|
|
||||||
// sqlExpressionResolver,
|
|
||||||
// creationContext
|
|
||||||
// );
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -166,7 +166,6 @@ public final class ExecuteWithIdTableHelper {
|
||||||
idTableReference,
|
idTableReference,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
executionContext.getSession().getFactory()
|
executionContext.getSession().getFactory()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ public final class ExecuteWithoutIdTableHelper {
|
||||||
rootTableReference,
|
rootTableReference,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
sessionFactory
|
sessionFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ public class CteTable {
|
||||||
tableValueConstructorReference,
|
tableValueConstructorReference,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
null,
|
null,
|
||||||
null,
|
|
||||||
sessionFactory
|
sessionFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,24 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
TableReference primaryTableReference,
|
TableReference primaryTableReference,
|
||||||
List<TableReferenceJoin> tableJoins,
|
List<TableReferenceJoin> tableJoins,
|
||||||
SqlAliasBase sqlAliasBase,
|
SqlAliasBase sqlAliasBase,
|
||||||
BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
|
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
|
||||||
this.primaryTableReference = primaryTableReference;
|
this.primaryTableReference = primaryTableReference;
|
||||||
this.tableJoins = tableJoins;
|
this.tableJoins = tableJoins;
|
||||||
|
this.tableReferenceJoinCreator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StandardTableGroup(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroupProducer tableGroupProducer,
|
||||||
|
LockMode lockMode,
|
||||||
|
TableReference primaryTableReference,
|
||||||
|
SqlAliasBase sqlAliasBase,
|
||||||
|
BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
|
||||||
|
this.primaryTableReference = primaryTableReference;
|
||||||
|
this.tableJoins = null;
|
||||||
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
|
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +73,14 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
return tableJoins == null ? Collections.emptyList() : tableJoins;
|
return tableJoins == null ? Collections.emptyList() : tableJoins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTableReferenceJoin(TableReferenceJoin join) {
|
||||||
|
if ( tableJoins == null ) {
|
||||||
|
tableJoins = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableJoins.add( join );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReference resolveTableReferenceInternal(String tableExpression) {
|
public TableReference resolveTableReferenceInternal(String tableExpression) {
|
||||||
final TableReference tableReference = super.resolveTableReferenceInternal( tableExpression );
|
final TableReference tableReference = super.resolveTableReferenceInternal( tableExpression );
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*/
|
|
||||||
package org.hibernate.sql.ast.tree.from;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
|
||||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class TableGroupBuilder implements TableReferenceCollector {
|
|
||||||
public static TableGroupBuilder builder(
|
|
||||||
NavigablePath path,
|
|
||||||
TableGroupProducer producer,
|
|
||||||
LockMode lockMode,
|
|
||||||
SqlAliasBase sqlAliasBase,
|
|
||||||
BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
return new TableGroupBuilder( path, producer, lockMode, sqlAliasBase, tableReferenceJoinCreator, sessionFactory );
|
|
||||||
}
|
|
||||||
|
|
||||||
private final NavigablePath path;
|
|
||||||
private final TableGroupProducer producer;
|
|
||||||
private final BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator;
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
|
||||||
|
|
||||||
private final SqlAliasBase sqlAliasBase;
|
|
||||||
private final LockMode lockMode;
|
|
||||||
|
|
||||||
private BiFunction<TableReference, TableReference,TableReferenceJoin> primaryJoinProducer;
|
|
||||||
|
|
||||||
private TableReference primaryTableReference;
|
|
||||||
private TableReference secondaryTableLhs;
|
|
||||||
|
|
||||||
private java.util.List<TableReferenceJoin> tableJoins;
|
|
||||||
|
|
||||||
private TableGroupBuilder(
|
|
||||||
NavigablePath path,
|
|
||||||
TableGroupProducer producer,
|
|
||||||
LockMode lockMode,
|
|
||||||
SqlAliasBase sqlAliasBase,
|
|
||||||
BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
this.path = path;
|
|
||||||
this.producer = producer;
|
|
||||||
this.lockMode = lockMode;
|
|
||||||
this.sqlAliasBase = sqlAliasBase;
|
|
||||||
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
|
|
||||||
this.sessionFactory = sessionFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NavigablePath getPath() {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionFactoryImplementor getSessionFactory() {
|
|
||||||
return sessionFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SqlAliasBase getSqlAliasBase() {
|
|
||||||
return sqlAliasBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryJoinProducer(BiFunction<TableReference, TableReference, TableReferenceJoin> primaryJoinProducer) {
|
|
||||||
this.primaryJoinProducer = primaryJoinProducer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableGroup build() {
|
|
||||||
if ( primaryTableReference == null ) {
|
|
||||||
throw new IllegalStateException( "Primary TableReference was not specified : " + path );
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StandardTableGroup(
|
|
||||||
path,
|
|
||||||
producer,
|
|
||||||
lockMode,
|
|
||||||
primaryTableReference,
|
|
||||||
tableJoins,
|
|
||||||
sqlAliasBase,
|
|
||||||
tableReferenceJoinCreator,
|
|
||||||
sessionFactory
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyPrimaryReference(TableReference tableReference) {
|
|
||||||
if ( primaryTableReference != null ) {
|
|
||||||
assert primaryJoinProducer != null;
|
|
||||||
addTableReferenceJoin( primaryJoinProducer.apply( primaryTableReference, tableReference ) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
primaryTableReference = tableReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
secondaryTableLhs = tableReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applySecondaryTableReferences(
|
|
||||||
TableReference tableReference,
|
|
||||||
SqlAstJoinType tableReferenceSqlAstJoinType,
|
|
||||||
TableReferenceJoinPredicateProducer predicateProducer) {
|
|
||||||
if ( primaryTableReference == null ) {
|
|
||||||
primaryTableReference = tableReference;
|
|
||||||
secondaryTableLhs = primaryTableReference;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addTableReferenceJoin(
|
|
||||||
new TableReferenceJoin(
|
|
||||||
tableReferenceSqlAstJoinType,
|
|
||||||
tableReference,
|
|
||||||
predicateProducer.producePredicate(
|
|
||||||
secondaryTableLhs,
|
|
||||||
tableReference,
|
|
||||||
tableReferenceSqlAstJoinType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTableReferenceJoin(TableReferenceJoin join) {
|
|
||||||
if ( tableJoins == null ) {
|
|
||||||
tableJoins = new ArrayList<>();
|
|
||||||
}
|
|
||||||
tableJoins.add( join );
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue