HHH-11433 Allow usage of KEY expression in a join
This commit is contained in:
parent
360fec82f1
commit
d5d350e5e7
|
@ -8,14 +8,21 @@ package org.hibernate.metamodel.model.domain.internal;
|
|||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SqmJoinable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmSingularJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
|
||||
public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> implements SqmJoinable<Object, J> {
|
||||
public EntitySqmPathSource(
|
||||
String localPathName,
|
||||
EntityDomainType<J> domainType,
|
||||
|
@ -51,4 +58,25 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
|
|||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<Object, J> createSqmJoin(
|
||||
SqmFrom<?, Object> lhs,
|
||||
SqmJoinType joinType,
|
||||
String alias,
|
||||
boolean fetched,
|
||||
SqmCreationState creationState) {
|
||||
return new SqmPluralPartJoin<>(
|
||||
lhs,
|
||||
this,
|
||||
alias,
|
||||
joinType,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getPathName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.spi.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
@ -45,7 +44,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
|||
private final String alias;
|
||||
|
||||
private ConsumerDelegate delegate;
|
||||
private boolean treated;
|
||||
private boolean nested;
|
||||
|
||||
public QualifiedJoinPathConsumer(
|
||||
SqmRoot<?> sqmRoot,
|
||||
|
@ -80,8 +79,12 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
|||
);
|
||||
}
|
||||
|
||||
public void setTreated(boolean treated) {
|
||||
this.treated = treated;
|
||||
public boolean isNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(boolean nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,13 +94,12 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
|||
|
||||
@Override
|
||||
public void consumeIdentifier(String identifier, boolean isBase, boolean isTerminal) {
|
||||
if ( isBase ) {
|
||||
assert delegate == null;
|
||||
delegate = resolveBase( identifier, !treated && isTerminal );
|
||||
if ( isBase && delegate == null ) {
|
||||
delegate = resolveBase( identifier, !nested && isTerminal );
|
||||
}
|
||||
else {
|
||||
assert delegate != null;
|
||||
delegate.consumeIdentifier( identifier, !treated && isTerminal );
|
||||
delegate.consumeIdentifier( identifier, !nested && isTerminal );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +196,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
|||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
final SqmAttributeJoin<Object, Object> join = ( (SqmJoinable) subPathSource ).createSqmJoin(
|
||||
final SqmJoin<Object, Object> join = ( (SqmJoinable<Object, Object>) subPathSource ).createSqmJoin(
|
||||
lhs,
|
||||
joinType,
|
||||
isTerminal ? alias : SqmCreationHelper.IMPLICIT_ALIAS,
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
|
||||
|
@ -410,6 +411,27 @@ public class QuerySplitter {
|
|||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<?, ?> visitPluralPartJoin(SqmPluralPartJoin<?, ?> join) {
|
||||
final SqmFrom<?, ?> sqmFrom = sqmFromCopyMap.get( join );
|
||||
if ( sqmFrom != null ) {
|
||||
return (SqmPluralPartJoin<?, ?>) sqmFrom;
|
||||
}
|
||||
final SqmFrom<?, ?> newLhs = (SqmFrom<?, ?>) sqmFromCopyMap.get( join.getLhs() );
|
||||
final SqmPluralPartJoin copy = new SqmPluralPartJoin<>(
|
||||
newLhs,
|
||||
join.getReferencedPathSource(),
|
||||
join.getExplicitAlias(),
|
||||
join.getSqmJoinType(),
|
||||
join.nodeBuilder()
|
||||
);
|
||||
getProcessingStateStack().getCurrent().getPathRegistry().register( copy );
|
||||
sqmFromCopyMap.put( join, copy );
|
||||
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
||||
newLhs.addSqmJoin( copy );
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmEntityJoin<?> visitQualifiedEntityJoin(SqmEntityJoin<?> join) {
|
||||
final SqmFrom<?, ?> sqmFrom = sqmFromCopyMap.get( join );
|
||||
|
|
|
@ -1660,7 +1660,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
if ( join instanceof SqmEntityJoin<?> ) {
|
||||
sqmRoot.addSqmJoin( join );
|
||||
}
|
||||
else {
|
||||
else if ( join instanceof SqmAttributeJoin<?, ?> ) {
|
||||
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) join;
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
if ( join.getExplicitAlias() != null ) {
|
||||
|
@ -4106,7 +4106,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPath<?> visitTreatedNavigablePath(HqlParser.TreatedNavigablePathContext ctx) {
|
||||
final DotIdentifierConsumer consumer = dotIdentifierConsumerStack.getCurrent();
|
||||
if ( consumer instanceof QualifiedJoinPathConsumer ) {
|
||||
( (QualifiedJoinPathConsumer) consumer ).setTreated( true );
|
||||
( (QualifiedJoinPathConsumer) consumer ).setNested( true );
|
||||
}
|
||||
consumeManagedTypeReference( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
||||
|
||||
|
@ -4189,21 +4189,67 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
@Override
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public SqmPath visitMapKeyNavigablePath(HqlParser.MapKeyNavigablePathContext ctx) {
|
||||
final DotIdentifierConsumer consumer = dotIdentifierConsumerStack.getCurrent();
|
||||
final boolean madeNested;
|
||||
if ( consumer instanceof QualifiedJoinPathConsumer ) {
|
||||
final QualifiedJoinPathConsumer qualifiedJoinPathConsumer = (QualifiedJoinPathConsumer) consumer;
|
||||
madeNested = !qualifiedJoinPathConsumer.isNested();
|
||||
if ( madeNested ) {
|
||||
qualifiedJoinPathConsumer.setNested( true );
|
||||
}
|
||||
}
|
||||
else {
|
||||
madeNested = false;
|
||||
}
|
||||
final SqmPath<?> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
|
||||
final boolean hasContinuation = ctx.getChildCount() == 5;
|
||||
|
||||
SqmPath<?> result;
|
||||
if ( sqmPath instanceof SqmMapJoin ) {
|
||||
final SqmMapJoin<?, ?, ?> sqmMapJoin = (SqmMapJoin<?, ?, ?>) sqmPath;
|
||||
result = sqmMapJoin.key();
|
||||
if ( consumer instanceof QualifiedJoinPathConsumer ) {
|
||||
if ( madeNested && !hasContinuation ) {
|
||||
// Reset the nested state before consuming the terminal identifier
|
||||
( (QualifiedJoinPathConsumer) consumer ).setNested( false );
|
||||
}
|
||||
consumer.consumeIdentifier( CollectionPart.Nature.INDEX.getName(), false, !hasContinuation );
|
||||
result = (SqmPath<?>) consumer.getConsumedPart();
|
||||
}
|
||||
else {
|
||||
result = sqmMapJoin.key();
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert sqmPath instanceof SqmPluralValuedSimplePath;
|
||||
final SqmPluralValuedSimplePath<?> mapPath = (SqmPluralValuedSimplePath<?>) sqmPath;
|
||||
result = mapPath.resolvePathPart( CollectionPart.Nature.INDEX.getName(), true, this );
|
||||
result = mapPath.resolvePathPart( CollectionPart.Nature.INDEX.getName(), !hasContinuation, this );
|
||||
}
|
||||
|
||||
if ( ctx.getChildCount() == 5 ) {
|
||||
result = consumeDomainPath( (HqlParser.DotIdentifierSequenceContext) ctx.getChild( 4 ).getChild( 1 ) );
|
||||
if ( hasContinuation ) {
|
||||
if ( madeNested ) {
|
||||
// Reset the nested state before consuming the terminal identifier
|
||||
( (QualifiedJoinPathConsumer) consumer ).setNested( false );
|
||||
}
|
||||
final HqlParser.DotIdentifierSequenceContext identCtx = (HqlParser.DotIdentifierSequenceContext) ctx.getChild( 4 )
|
||||
.getChild( 1 );
|
||||
if ( consumer instanceof QualifiedJoinPathConsumer ) {
|
||||
result = consumeDomainPath( identCtx );
|
||||
}
|
||||
else {
|
||||
dotIdentifierConsumerStack.push(
|
||||
new BasicDotIdentifierConsumer( result, this ) {
|
||||
@Override
|
||||
protected void reset() {
|
||||
}
|
||||
}
|
||||
);
|
||||
try {
|
||||
result = consumeDomainPath( identCtx );
|
||||
}
|
||||
finally {
|
||||
dotIdentifierConsumerStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMaxElementPath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmMaxIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmAny;
|
||||
|
@ -130,6 +131,8 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitCrossJoin(SqmCrossJoin<?> joinedFromElement);
|
||||
|
||||
T visitPluralPartJoin(SqmPluralPartJoin<?, ?> joinedFromElement);
|
||||
|
||||
T visitQualifiedEntityJoin(SqmEntityJoin<?> joinedFromElement);
|
||||
|
||||
T visitQualifiedAttributeJoin(SqmAttributeJoin<?, ?> joinedFromElement);
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.query.hql.spi.SqmCreationState;
|
|||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
/**
|
||||
* Specialization for attributes that that can be used in creating SQM joins
|
||||
|
@ -19,9 +20,9 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmJoinable {
|
||||
SqmAttributeJoin createSqmJoin(
|
||||
SqmFrom lhs,
|
||||
public interface SqmJoinable<O, E> {
|
||||
SqmJoin<O, E> createSqmJoin(
|
||||
SqmFrom<?, O> lhs,
|
||||
SqmJoinType joinType,
|
||||
String alias,
|
||||
boolean fetched,
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMaxElementPath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmMaxIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
|
@ -505,6 +506,17 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPluralPartJoin(SqmPluralPartJoin<?, ?> joinedFromElement) {
|
||||
processStanza(
|
||||
"plural-part",
|
||||
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
|
||||
() -> processJoins( joinedFromElement )
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean inJoinPredicate;
|
||||
|
||||
private void processJoinPredicate(SqmQualifiedJoin<?, ?> joinedFromElement) {
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.query.sqm.tree.domain.SqmMaxIndexPath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmMinElementPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
|
@ -249,6 +250,13 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
|||
return joinedFromElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPluralPartJoin(SqmPluralPartJoin<?, ?> joinedFromElement) {
|
||||
joinedFromElement.visitReusablePaths( path -> path.accept( this ) );
|
||||
joinedFromElement.visitSqmJoins( sqmJoin -> sqmJoin.accept( this ) );
|
||||
return joinedFromElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitQualifiedEntityJoin(SqmEntityJoin<?> joinedFromElement) {
|
||||
joinedFromElement.visitReusablePaths( path -> path.accept( this ) );
|
||||
|
|
|
@ -101,6 +101,7 @@ import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
|||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedRootJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralPartJoin;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression;
|
||||
|
@ -114,7 +115,6 @@ import org.hibernate.sql.ast.tree.from.QueryPartTableGroup;
|
|||
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.exec.internal.VersionTypeSeedParameterSpecification;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.query.BinaryArithmeticOperator;
|
||||
|
@ -126,8 +126,6 @@ import org.hibernate.query.QueryLogging;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.UnaryArithmeticOperator;
|
||||
import org.hibernate.query.criteria.JpaPath;
|
||||
import org.hibernate.query.internal.QueryHelper;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.spi.QueryParameterBinding;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
|
@ -138,10 +136,8 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
import org.hibernate.query.sqm.SqmQuerySource;
|
||||
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
|
||||
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.DiscriminatedAssociationPathInterpretation;
|
||||
|
@ -157,7 +153,6 @@ import org.hibernate.query.sqm.sql.internal.SqmMapEntryResult;
|
|||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.TypeHelper;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
|
||||
|
@ -170,8 +165,6 @@ import org.hibernate.query.sqm.tree.domain.AbstractSqmSpecificPluralPartPath;
|
|||
import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelatedRootJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
|
||||
|
@ -183,7 +176,6 @@ import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
|||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot;
|
||||
import org.hibernate.query.sqm.tree.expression.Conversion;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
|
||||
|
@ -208,7 +200,6 @@ import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||
|
@ -227,7 +218,6 @@ import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
|||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
|
@ -304,21 +294,16 @@ import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
|||
import org.hibernate.sql.ast.tree.expression.Format;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.Over;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Star;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||
import org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.LazyTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.PluralTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||
|
@ -329,7 +314,6 @@ import org.hibernate.sql.ast.tree.predicate.BetweenPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.ExistsPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.GroupedPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
|
||||
|
@ -351,7 +335,6 @@ import org.hibernate.sql.ast.tree.update.Assignment;
|
|||
import org.hibernate.sql.ast.tree.update.UpdateStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParametersImpl;
|
||||
import org.hibernate.sql.exec.internal.VersionTypeSeedParameterSpecification;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameters;
|
||||
|
@ -2469,6 +2452,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
else if ( sqmJoin instanceof SqmEntityJoin<?> ) {
|
||||
return consumeEntityJoin( ( (SqmEntityJoin<?>) sqmJoin ), lhsTableGroup, transitive );
|
||||
}
|
||||
else if ( sqmJoin instanceof SqmPluralPartJoin<?, ?> ) {
|
||||
return consumePluralPartJoin( ( (SqmPluralPartJoin<?, ?>) sqmJoin ), ownerTableGroup, transitive );
|
||||
}
|
||||
else {
|
||||
throw new InterpretationException( "Could not resolve SqmJoin [" + sqmJoin.getNavigablePath() + "] to TableGroupJoin" );
|
||||
}
|
||||
|
@ -2694,6 +2680,31 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return tableGroup;
|
||||
}
|
||||
|
||||
private TableGroup consumePluralPartJoin(SqmPluralPartJoin<?, ?> sqmJoin, TableGroup lhsTableGroup, boolean transitive) {
|
||||
final PluralTableGroup pluralTableGroup = (PluralTableGroup) lhsTableGroup;
|
||||
final TableGroup tableGroup = getPluralPartTableGroup( pluralTableGroup, sqmJoin.getReferencedPathSource() );
|
||||
getFromClauseIndex().register( sqmJoin, tableGroup );
|
||||
|
||||
assert sqmJoin.getJoinPredicate() == null;
|
||||
if ( transitive ) {
|
||||
consumeExplicitJoins( sqmJoin, tableGroup );
|
||||
}
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
private TableGroup getPluralPartTableGroup(PluralTableGroup pluralTableGroup, SqmPathSource<?> pathSource) {
|
||||
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( pathSource.getPathName() );
|
||||
if ( nature != null ) {
|
||||
switch ( nature ) {
|
||||
case INDEX:
|
||||
return pluralTableGroup.getIndexTableGroup();
|
||||
case ELEMENT:
|
||||
return pluralTableGroup.getElementTableGroup();
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException( "Unsupported plural part join nature: " + nature );
|
||||
}
|
||||
|
||||
private <X> X prepareReusablePath(SqmPath<?> sqmPath, Supplier<X> supplier) {
|
||||
final Consumer<TableGroup> implicitJoinChecker;
|
||||
if ( getCurrentProcessingState() instanceof SqlAstQueryPartProcessingState ) {
|
||||
|
@ -2719,6 +2730,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
else {
|
||||
parentPath = sqmPath.getParentPath();
|
||||
}
|
||||
if ( parentPath == null ) {
|
||||
return null;
|
||||
}
|
||||
final TableGroup tableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() );
|
||||
if ( tableGroup == null ) {
|
||||
final TableGroup parentTableGroup = prepareReusablePath(
|
||||
|
@ -2923,6 +2937,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
throw new InterpretationException( "SqmCrossJoin not yet resolved to TableGroup" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPluralPartJoin(SqmPluralPartJoin<?, ?> sqmJoin) {
|
||||
// todo (6.0) : have this resolve to TableGroup instead?
|
||||
// - trying to remove tracking of TableGroupJoin in the x-refs
|
||||
|
||||
final TableGroup existing = getFromClauseAccess().findTableGroup( sqmJoin.getNavigablePath() );
|
||||
if ( existing != null ) {
|
||||
log.tracef( "SqmPluralPartJoin [%s] resolved to existing TableGroup [%s]", sqmJoin, existing );
|
||||
return visitTableGroup( existing, sqmJoin );
|
||||
}
|
||||
|
||||
throw new InterpretationException( "SqmPluralPartJoin not yet resolved to TableGroup" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression visitQualifiedEntityJoin(SqmEntityJoin sqmJoin) {
|
||||
// todo (6.0) : have this resolve to TableGroup instead?
|
||||
|
@ -4165,6 +4193,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final MappingMetamodel domainModel = getCreationContext().getDomainModel();
|
||||
if ( sqmExpression instanceof SqmPath ) {
|
||||
log.debugf( "Determining mapping-model type for SqmPath : %s ", sqmExpression );
|
||||
prepareReusablePath( (SqmPath<?>) sqmExpression, () -> null );
|
||||
return SqmMappingModelHelper.resolveMappingModelExpressable(
|
||||
sqmExpression,
|
||||
domainModel,
|
||||
|
@ -5547,9 +5576,27 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
// otherwise - no special case...
|
||||
inferrableTypeAccessStack.push(
|
||||
() -> {
|
||||
for ( SqmExpression<?> listExpression : predicate.getListExpressions() ) {
|
||||
final MappingModelExpressable<?> mapping = determineValueMapping( listExpression );
|
||||
if ( mapping != null ) {
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
final Expression testExpression;
|
||||
try {
|
||||
testExpression = (Expression) predicate.getTestExpression().accept( this );
|
||||
}
|
||||
finally {
|
||||
inferrableTypeAccessStack.pop();
|
||||
}
|
||||
|
||||
final InListPredicate inPredicate = new InListPredicate(
|
||||
(Expression) predicate.getTestExpression().accept( this ),
|
||||
testExpression,
|
||||
predicate.isNegated(),
|
||||
getBooleanType()
|
||||
);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.query.sqm.tree.domain;
|
||||
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SqmCorrelatedPluralPartJoin<O, T> extends SqmPluralPartJoin<O, T> implements SqmCorrelation<O, T> {
|
||||
|
||||
private final SqmCorrelatedRootJoin<O> correlatedRootJoin;
|
||||
private final SqmPluralPartJoin<O, T> correlationParent;
|
||||
|
||||
public SqmCorrelatedPluralPartJoin(SqmPluralPartJoin<O, T> correlationParent) {
|
||||
super(
|
||||
(SqmFrom<?, O>) correlationParent.getLhs(),
|
||||
correlationParent.getReferencedPathSource(),
|
||||
null,
|
||||
SqmJoinType.INNER,
|
||||
correlationParent.nodeBuilder()
|
||||
);
|
||||
this.correlatedRootJoin = SqmCorrelatedRootJoin.create( correlationParent, this );
|
||||
this.correlationParent = correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<O, T> getCorrelationParent() {
|
||||
return correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<T> getWrappedPath() {
|
||||
return correlationParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCorrelated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmRoot<O> getCorrelatedRoot() {
|
||||
return correlatedRootJoin;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.query.sqm.tree.domain;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.spi.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SqmPluralPartJoin<O,T> extends AbstractSqmJoin<O,T> implements DomainResultProducer<T>, SqmQualifiedJoin<O, T> {
|
||||
|
||||
public SqmPluralPartJoin(
|
||||
SqmFrom<?,O> lhs,
|
||||
SqmPathSource<T> joinedNavigable,
|
||||
String alias,
|
||||
SqmJoinType joinType,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super(
|
||||
SqmCreationHelper.buildSubNavigablePath( lhs, joinedNavigable.getPathName(), alias ),
|
||||
joinedNavigable,
|
||||
lhs,
|
||||
alias == SqmCreationHelper.IMPLICIT_ALIAS ? null : alias,
|
||||
joinType,
|
||||
nodeBuilder
|
||||
);
|
||||
}
|
||||
|
||||
protected SqmPluralPartJoin(
|
||||
SqmFrom<?, O> lhs,
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource<T> joinedNavigable,
|
||||
String alias,
|
||||
SqmJoinType joinType,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super(
|
||||
navigablePath,
|
||||
joinedNavigable,
|
||||
lhs,
|
||||
alias == SqmCreationHelper.IMPLICIT_ALIAS ? null : alias,
|
||||
joinType,
|
||||
nodeBuilder
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getJoinPredicate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJoinPredicate(SqmPredicate predicate) {
|
||||
throw new UnsupportedOperationException( "Setting a predicate for a plural part join is unsupported!" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitPluralPartJoin( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPluralPartJoin<O,T,S> treatAs(Class<S> treatJavaType) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPluralPartJoin<O,T,S> treatAs(EntityDomainType<S> treatTarget) {
|
||||
return treatAs( treatTarget, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPluralPartJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPluralPartJoin<O,T,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
final SqmTreatedPluralPartJoin<O, T, S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedPluralPartJoin<>( this, treatTarget, alias ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmCorrelatedPluralPartJoin<O, T> createCorrelation() {
|
||||
return new SqmCorrelatedPluralPartJoin<>( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
"SqmPluralPartJoin(%s : %s)",
|
||||
getNavigablePath().getFullPath(),
|
||||
getReferencedPathSource().getPathName()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,16 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> implemen
|
|||
super( lhs, joinedNavigable, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmSingularJoin(
|
||||
SqmFrom<?,O> lhs,
|
||||
SqmJoinable joinedNavigable,
|
||||
String alias,
|
||||
SqmJoinType joinType,
|
||||
boolean fetched,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( lhs, joinedNavigable, alias, joinType, fetched, nodeBuilder );
|
||||
}
|
||||
|
||||
protected SqmSingularJoin(
|
||||
SqmFrom<?, O> lhs,
|
||||
NavigablePath navigablePath,
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.query.sqm.tree.domain;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmTreatedPluralPartJoin<O,T, S extends T> extends SqmPluralPartJoin<O,S> implements SqmTreatedPath<T,S> {
|
||||
private final SqmPluralPartJoin<O,T> wrappedPath;
|
||||
private final EntityDomainType<S> treatTarget;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SqmTreatedPluralPartJoin(
|
||||
SqmPluralPartJoin<O,T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
(SqmFrom<?, O>) wrappedPath.getLhs(),
|
||||
wrappedPath.getNavigablePath().treatAs(
|
||||
treatTarget.getHibernateEntityName(),
|
||||
alias
|
||||
),
|
||||
(SqmPathSource<S>) wrappedPath.getReferencedPathSource(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
this.wrappedPath = wrappedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSqmJoin(SqmJoin<S, ?> join) {
|
||||
super.addSqmJoin( join );
|
||||
//noinspection unchecked
|
||||
wrappedPath.addSqmJoin( (SqmJoin<T, ?>) join );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPluralPartJoin<O,T> getWrappedPath() {
|
||||
return wrappedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDomainType<S> getTreatTarget() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<S> getNodeType() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
sb.append( "treat(" );
|
||||
wrappedPath.appendHqlString( sb );
|
||||
sb.append( " as " );
|
||||
sb.append( treatTarget.getName() );
|
||||
sb.append( ')' );
|
||||
}
|
||||
}
|
|
@ -153,6 +153,6 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
|
|||
|
||||
@Override
|
||||
public JavaType<T> getJavaTypeDescriptor() {
|
||||
return getNodeType().getExpressableJavaTypeDescriptor();
|
||||
return getNodeType() == null ? null : getNodeType().getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
* 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.test.hql;
|
||||
package org.hibernate.orm.test.hql;
|
||||
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.Arrays;
|
||||
|
@ -55,6 +57,7 @@ public class CollectionMapWithComponentValueTest extends BaseCoreFunctionalTestC
|
|||
@Override
|
||||
protected void prepareTest() throws Exception {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
keyValue.base = null;
|
||||
s.save( keyValue );
|
||||
|
||||
BaseTestEntity baseTestEntity1 = new BaseTestEntity();
|
||||
|
@ -67,6 +70,8 @@ public class CollectionMapWithComponentValueTest extends BaseCoreFunctionalTestC
|
|||
baseTestEntity1.entities.add( testEntity );
|
||||
s.save( baseTestEntity1 );
|
||||
|
||||
keyValue.base = baseTestEntity1;
|
||||
|
||||
KeyValue keyValue2 = new KeyValue( "key2" );
|
||||
s.save( keyValue2 );
|
||||
BaseTestEntity baseTestEntity2 = new BaseTestEntity();
|
||||
|
@ -197,6 +202,37 @@ public class CollectionMapWithComponentValueTest extends BaseCoreFunctionalTestC
|
|||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11433")
|
||||
public void testJoinMapKey() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
// Assert that a left join is used for joining the map key entity table
|
||||
List keyValues= s.createQuery( "select k from BaseTestEntity bte left join bte.entities te left join te.values v left join key(v) k" ).list();
|
||||
System.out.println( keyValues );
|
||||
assertEquals( 2, keyValues.size() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11433")
|
||||
public void testJoinMapKeyAssociation() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
List keyValues= s.createQuery( "select b from BaseTestEntity bte left join bte.entities te left join te.values v left join key(v) k join k.base b" ).list();
|
||||
System.out.println( keyValues );
|
||||
assertEquals( 1, keyValues.size() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11433")
|
||||
public void testJoinMapKeyAssociationImplicit() {
|
||||
doInHibernate( this::sessionFactory, s -> {
|
||||
List keyValues= s.createQuery( "select b from BaseTestEntity bte left join bte.entities te left join te.values v join key(v).base b" ).list();
|
||||
System.out.println( keyValues );
|
||||
assertEquals( 1, keyValues.size() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCleanupTestDataRequired() {
|
||||
return true;
|
||||
|
@ -233,6 +269,9 @@ public class CollectionMapWithComponentValueTest extends BaseCoreFunctionalTestC
|
|||
|
||||
String name;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
BaseTestEntity base;
|
||||
|
||||
public KeyValue() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue