HHH-17411 Fix fetch join on treated join leads to not cause owner not selected error
This commit is contained in:
parent
a3f7637585
commit
78c9ccf64f
|
@ -21,6 +21,7 @@ import org.hibernate.query.sqm.tree.SqmJoinType;
|
|||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCteJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
@ -276,9 +277,14 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
|||
|
||||
@Override
|
||||
public void consumeTreat(String entityName, boolean isTerminal) {
|
||||
currentPath = isTerminal
|
||||
? currentPath.treatAs( treatTarget( entityName ), alias)
|
||||
: currentPath.treatAs( treatTarget( entityName ) );
|
||||
if ( isTerminal ) {
|
||||
currentPath = fetch
|
||||
? ( (SqmAttributeJoin<?, ?>) currentPath ).treatAs( treatTarget( entityName ), alias, true )
|
||||
: currentPath.treatAs( treatTarget( entityName ), alias );
|
||||
}
|
||||
else {
|
||||
currentPath = currentPath.treatAs( treatTarget( entityName ) );
|
||||
}
|
||||
creationState.getCurrentProcessingState().getPathRegistry().register( currentPath );
|
||||
}
|
||||
|
||||
|
|
|
@ -132,9 +132,19 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
|||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
return treatAs( treatTarget, alias, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias, boolean fetch) {
|
||||
final SqmTreatedBagJoin<O,E,S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedBagJoin<>( this, treatTarget, alias ) );
|
||||
return addTreat( new SqmTreatedBagJoin<>( this, treatTarget, alias, fetch ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
|
|
@ -139,9 +139,19 @@ public class SqmListJoin<O,E>
|
|||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
return treatAs( treatTarget, alias, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias, boolean fetch) {
|
||||
final SqmTreatedListJoin<O,E,S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedListJoin<>( this, treatTarget, alias ) );
|
||||
return addTreat( new SqmTreatedListJoin<>( this, treatTarget, alias, fetch ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
|
|
@ -151,9 +151,19 @@ public class SqmMapJoin<O, K, V>
|
|||
|
||||
@Override
|
||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
return treatAs( treatTarget, alias, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(EntityDomainType<S> treatTarget, String alias, boolean fetch) {
|
||||
final SqmTreatedMapJoin<O, K, V, S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedMapJoin<>( this, treatTarget, alias ) );
|
||||
return addTreat( new SqmTreatedMapJoin<>( this, treatTarget, alias, fetch ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
|
|
@ -132,9 +132,19 @@ public class SqmSetJoin<O, E>
|
|||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
return treatAs( treatTarget, alias, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias, boolean fetch) {
|
||||
final SqmTreatedSetJoin<O, E, S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedSetJoin<>( this, treatTarget, alias ) );
|
||||
return addTreat( new SqmTreatedSetJoin<>( this, treatTarget, alias, fetch ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
|
|
@ -110,9 +110,19 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
|||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
||||
return treatAs( treatTarget, alias, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(EntityDomainType<S> treatTarget, String alias, boolean fetch) {
|
||||
final SqmTreatedSingularJoin<O, T, S> treat = findTreat( treatTarget, alias );
|
||||
if ( treat == null ) {
|
||||
return addTreat( new SqmTreatedSingularJoin<>( this, treatTarget, alias ) );
|
||||
return addTreat( new SqmTreatedSingularJoin<>( this, treatTarget, alias, fetch ) );
|
||||
}
|
||||
return treat;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,14 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
SqmBagJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
this( wrappedPath, treatTarget, alias, false );
|
||||
}
|
||||
|
||||
public SqmTreatedBagJoin(
|
||||
SqmBagJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -35,7 +43,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -46,7 +54,8 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
NavigablePath navigablePath,
|
||||
SqmBagJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -76,7 +85,8 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
getNavigablePath(),
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
getExplicitAlias(),
|
||||
isFetched()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
|
|
|
@ -28,6 +28,14 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
SqmListJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
this( wrappedPath, treatTarget, alias, false );
|
||||
}
|
||||
|
||||
public SqmTreatedListJoin(
|
||||
SqmListJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -37,7 +45,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -48,7 +56,8 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
NavigablePath navigablePath,
|
||||
SqmListJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -56,7 +65,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -75,7 +84,8 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
getNavigablePath(),
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
getExplicitAlias(),
|
||||
isFetched()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
|
|
|
@ -24,6 +24,14 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
SqmMapJoin<O, K, V> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
this( wrappedPath, treatTarget, alias, false );
|
||||
}
|
||||
|
||||
public SqmTreatedMapJoin(
|
||||
SqmMapJoin<O, K, V> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -33,7 +41,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -44,7 +52,8 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
NavigablePath navigablePath,
|
||||
SqmMapJoin<O, K, V> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -52,7 +61,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -71,7 +80,8 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
getNavigablePath(),
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
getExplicitAlias(),
|
||||
isFetched()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
|
|
|
@ -26,6 +26,14 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
SqmSetJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
this( wrappedPath, treatTarget, alias, false );
|
||||
}
|
||||
|
||||
public SqmTreatedSetJoin(
|
||||
SqmSetJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -35,7 +43,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -46,7 +54,8 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
NavigablePath navigablePath,
|
||||
SqmSetJoin<O, T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -54,7 +63,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -73,7 +82,8 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
getNavigablePath(),
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
getExplicitAlias(),
|
||||
isFetched()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
|
|
|
@ -25,6 +25,14 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
SqmSingularJoin<O,T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
this( wrappedPath, treatTarget, alias, false );
|
||||
}
|
||||
|
||||
public SqmTreatedSingularJoin(
|
||||
SqmSingularJoin<O,T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -35,7 +43,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -46,7 +54,8 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
NavigablePath navigablePath,
|
||||
SqmSingularJoin<O,T> wrappedPath,
|
||||
EntityDomainType<S> treatTarget,
|
||||
String alias) {
|
||||
String alias,
|
||||
boolean fetched) {
|
||||
//noinspection unchecked
|
||||
super(
|
||||
wrappedPath.getLhs(),
|
||||
|
@ -54,7 +63,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||
alias,
|
||||
wrappedPath.getSqmJoinType(),
|
||||
wrappedPath.isFetched(),
|
||||
fetched,
|
||||
wrappedPath.nodeBuilder()
|
||||
);
|
||||
this.treatTarget = treatTarget;
|
||||
|
@ -73,7 +82,8 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
getNavigablePath(),
|
||||
wrappedPath.copy( context ),
|
||||
treatTarget,
|
||||
getExplicitAlias()
|
||||
getExplicitAlias(),
|
||||
isFetched()
|
||||
)
|
||||
);
|
||||
copyTo( path, context );
|
||||
|
|
|
@ -48,6 +48,16 @@ public interface SqmAttributeJoin<O,T> extends SqmQualifiedJoin<O,T>, JpaFetch<O
|
|||
@Override
|
||||
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatTarget);
|
||||
|
||||
@Override
|
||||
<S extends T> SqmAttributeJoin<O, S> treatAs(Class<S> treatJavaType, String alias);
|
||||
|
||||
@Override
|
||||
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatJavaType, String alias);
|
||||
|
||||
<S extends T> SqmAttributeJoin<O, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch);
|
||||
|
||||
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatJavaType, String alias, boolean fetch);
|
||||
|
||||
/*
|
||||
@deprecated not used anymore
|
||||
*/
|
||||
|
|
|
@ -489,7 +489,10 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
}
|
||||
|
||||
for ( SqmRoot<?> root : roots ) {
|
||||
validateFetchOwners( selectedFromSet, root );
|
||||
validateFetchOwners( selectedFromSet, root, root );
|
||||
for ( SqmFrom<?, ?> sqmTreat : root.getSqmTreats() ) {
|
||||
validateFetchOwners( selectedFromSet, root, sqmTreat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,8 +534,8 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
}
|
||||
}
|
||||
|
||||
private void validateFetchOwners(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner) {
|
||||
for ( SqmJoin<?, ?> sqmJoin : owner.getSqmJoins() ) {
|
||||
private void validateFetchOwners(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner, SqmFrom<?, ?> joinContainer) {
|
||||
for ( SqmJoin<?, ?> sqmJoin : joinContainer.getSqmJoins() ) {
|
||||
if ( sqmJoin instanceof SqmAttributeJoin<?, ?> ) {
|
||||
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmJoin;
|
||||
if ( attributeJoin.isFetched() ) {
|
||||
|
@ -541,19 +544,27 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
continue;
|
||||
}
|
||||
}
|
||||
validateFetchOwners( selectedFromSet, sqmJoin );
|
||||
}
|
||||
for ( SqmFrom<?, ?> sqmTreat : owner.getSqmTreats() ) {
|
||||
validateFetchOwners( selectedFromSet, sqmTreat );
|
||||
for ( SqmFrom<?, ?> sqmTreat : sqmJoin.getSqmTreats() ) {
|
||||
if ( sqmTreat instanceof SqmAttributeJoin<?, ?> ) {
|
||||
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmTreat;
|
||||
if ( attributeJoin.isFetched() ) {
|
||||
assertFetchOwner( selectedFromSet, owner, attributeJoin );
|
||||
// Only need to check the first level
|
||||
continue;
|
||||
}
|
||||
}
|
||||
validateFetchOwners( selectedFromSet, sqmJoin, sqmTreat );
|
||||
}
|
||||
validateFetchOwners( selectedFromSet, sqmJoin, sqmJoin );
|
||||
}
|
||||
}
|
||||
|
||||
private void assertFetchOwner(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner, SqmJoin<?, ?> sqmJoin) {
|
||||
private void assertFetchOwner(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner, SqmJoin<?, ?> fetchJoin) {
|
||||
if ( !selectedFromSet.contains( owner ) ) {
|
||||
throw new SemanticException(
|
||||
"Query specified join fetching, but the owner " +
|
||||
"of the fetched association was not present in the select list " +
|
||||
"[" + sqmJoin.asLoggableText() + "]"
|
||||
"[" + fetchJoin.asLoggableText() + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
package org.hibernate.orm.test.query.hql.treat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.persistence.OneToOne;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
HqlTreatJoinFetchTest.TestEntity.class,
|
||||
HqlTreatJoinFetchTest.BaseEntity.class,
|
||||
HqlTreatJoinFetchTest.JoinedEntity.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
@JiraKey("HHH-17411")
|
||||
public class HqlTreatJoinFetchTest {
|
||||
|
||||
@BeforeAll
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
JoinedEntity joined = new JoinedEntity( 1, "joined" );
|
||||
TestEntity testEntity = new TestEntity( 2, "test", joined );
|
||||
|
||||
session.persist( testEntity );
|
||||
session.persist( joined );
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTreatJoinFetch(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
QueryImplementor<TestEntity> query = session.createQuery(
|
||||
"select t from TestEntity t join fetch treat(t.joined as JoinedEntity) j left join fetch j.testEntity e",
|
||||
TestEntity.class
|
||||
);
|
||||
List<TestEntity> result = query.list();
|
||||
assertThat( result.size() ).isEqualTo( 1 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinFetchRootTreat(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
QueryImplementor<TestEntity> query = session.createQuery(
|
||||
"select t from BaseEntity t join fetch treat(t as JoinedEntity).testEntity j left join fetch j.joined2 e",
|
||||
TestEntity.class
|
||||
);
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@MappedSuperclass
|
||||
public static abstract class AbstractEntity {
|
||||
|
||||
public AbstractEntity() {
|
||||
}
|
||||
|
||||
public AbstractEntity(BaseEntity joined) {
|
||||
this.joined = joined;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
private BaseEntity joined;
|
||||
|
||||
public BaseEntity getJoined() {
|
||||
return joined;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
public static class TestEntity extends AbstractEntity {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private JoinedEntity joined2;
|
||||
|
||||
public TestEntity() {
|
||||
}
|
||||
|
||||
public TestEntity(long id, String name, JoinedEntity joined) {
|
||||
super( joined );
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "BaseEntity")
|
||||
public static abstract class BaseEntity {
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public BaseEntity() {
|
||||
}
|
||||
|
||||
public BaseEntity(long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "JoinedEntity")
|
||||
public static class JoinedEntity extends BaseEntity {
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private TestEntity testEntity;
|
||||
|
||||
public JoinedEntity() {
|
||||
}
|
||||
|
||||
public JoinedEntity(long id, String name) {
|
||||
super( id, name );
|
||||
}
|
||||
|
||||
public TestEntity getTestEntity() {
|
||||
return testEntity;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue