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.cte.SqmCteStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
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.SqmCteJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
|
@ -276,9 +277,14 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consumeTreat(String entityName, boolean isTerminal) {
|
public void consumeTreat(String entityName, boolean isTerminal) {
|
||||||
currentPath = isTerminal
|
if ( isTerminal ) {
|
||||||
? currentPath.treatAs( treatTarget( entityName ), alias)
|
currentPath = fetch
|
||||||
: currentPath.treatAs( treatTarget( entityName ) );
|
? ( (SqmAttributeJoin<?, ?>) currentPath ).treatAs( treatTarget( entityName ), alias, true )
|
||||||
|
: currentPath.treatAs( treatTarget( entityName ), alias );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentPath = currentPath.treatAs( treatTarget( entityName ) );
|
||||||
|
}
|
||||||
creationState.getCurrentProcessingState().getPathRegistry().register( currentPath );
|
creationState.getCurrentProcessingState().getPathRegistry().register( currentPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,9 +132,19 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
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 );
|
final SqmTreatedBagJoin<O,E,S> treat = findTreat( treatTarget, alias );
|
||||||
if ( treat == null ) {
|
if ( treat == null ) {
|
||||||
return addTreat( new SqmTreatedBagJoin<>( this, treatTarget, alias ) );
|
return addTreat( new SqmTreatedBagJoin<>( this, treatTarget, alias, fetch ) );
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,9 +139,19 @@ public class SqmListJoin<O,E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
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 );
|
final SqmTreatedListJoin<O,E,S> treat = findTreat( treatTarget, alias );
|
||||||
if ( treat == null ) {
|
if ( treat == null ) {
|
||||||
return addTreat( new SqmTreatedListJoin<>( this, treatTarget, alias ) );
|
return addTreat( new SqmTreatedListJoin<>( this, treatTarget, alias, fetch ) );
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,19 @@ public class SqmMapJoin<O, K, V>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
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 );
|
final SqmTreatedMapJoin<O, K, V, S> treat = findTreat( treatTarget, alias );
|
||||||
if ( treat == null ) {
|
if ( treat == null ) {
|
||||||
return addTreat( new SqmTreatedMapJoin<>( this, treatTarget, alias ) );
|
return addTreat( new SqmTreatedMapJoin<>( this, treatTarget, alias, fetch ) );
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,9 +132,19 @@ public class SqmSetJoin<O, E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
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 );
|
final SqmTreatedSetJoin<O, E, S> treat = findTreat( treatTarget, alias );
|
||||||
if ( treat == null ) {
|
if ( treat == null ) {
|
||||||
return addTreat( new SqmTreatedSetJoin<>( this, treatTarget, alias ) );
|
return addTreat( new SqmTreatedSetJoin<>( this, treatTarget, alias, fetch ) );
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,9 +110,19 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(EntityDomainType<S> treatTarget, String alias) {
|
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 );
|
final SqmTreatedSingularJoin<O, T, S> treat = findTreat( treatTarget, alias );
|
||||||
if ( treat == null ) {
|
if ( treat == null ) {
|
||||||
return addTreat( new SqmTreatedSingularJoin<>( this, treatTarget, alias ) );
|
return addTreat( new SqmTreatedSingularJoin<>( this, treatTarget, alias, fetch ) );
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
SqmBagJoin<O, T> wrappedPath,
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmTreatedBagJoin(
|
||||||
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
|
EntityDomainType<S> treatTarget,
|
||||||
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -35,7 +43,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -46,7 +54,8 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmBagJoin<O, T> wrappedPath,
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -76,7 +85,8 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
treatTarget,
|
treatTarget,
|
||||||
getExplicitAlias()
|
getExplicitAlias(),
|
||||||
|
isFetched()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
copyTo( path, context );
|
copyTo( path, context );
|
||||||
|
|
|
@ -28,6 +28,14 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
SqmListJoin<O, T> wrappedPath,
|
SqmListJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmTreatedListJoin(
|
||||||
|
SqmListJoin<O, T> wrappedPath,
|
||||||
|
EntityDomainType<S> treatTarget,
|
||||||
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -37,7 +45,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -48,7 +56,8 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmListJoin<O, T> wrappedPath,
|
SqmListJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -56,7 +65,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -75,7 +84,8 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
treatTarget,
|
treatTarget,
|
||||||
getExplicitAlias()
|
getExplicitAlias(),
|
||||||
|
isFetched()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
copyTo( path, context );
|
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,
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmTreatedMapJoin(
|
||||||
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
|
EntityDomainType<S> treatTarget,
|
||||||
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
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(),
|
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -44,7 +52,8 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmMapJoin<O, K, V> wrappedPath,
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
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(),
|
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -71,7 +80,8 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
treatTarget,
|
treatTarget,
|
||||||
getExplicitAlias()
|
getExplicitAlias(),
|
||||||
|
isFetched()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
copyTo( path, context );
|
copyTo( path, context );
|
||||||
|
|
|
@ -26,6 +26,14 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
SqmSetJoin<O, T> wrappedPath,
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmTreatedSetJoin(
|
||||||
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
|
EntityDomainType<S> treatTarget,
|
||||||
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -35,7 +43,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -46,7 +54,8 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmSetJoin<O, T> wrappedPath,
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -54,7 +63,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -73,7 +82,8 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
treatTarget,
|
treatTarget,
|
||||||
getExplicitAlias()
|
getExplicitAlias(),
|
||||||
|
isFetched()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
copyTo( path, context );
|
copyTo( path, context );
|
||||||
|
|
|
@ -25,6 +25,14 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
SqmSingularJoin<O,T> wrappedPath,
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmTreatedSingularJoin(
|
||||||
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
|
EntityDomainType<S> treatTarget,
|
||||||
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -35,7 +43,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -46,7 +54,8 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmSingularJoin<O,T> wrappedPath,
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias,
|
||||||
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
|
@ -54,7 +63,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
wrappedPath.isFetched(),
|
fetched,
|
||||||
wrappedPath.nodeBuilder()
|
wrappedPath.nodeBuilder()
|
||||||
);
|
);
|
||||||
this.treatTarget = treatTarget;
|
this.treatTarget = treatTarget;
|
||||||
|
@ -73,7 +82,8 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
treatTarget,
|
treatTarget,
|
||||||
getExplicitAlias()
|
getExplicitAlias(),
|
||||||
|
isFetched()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
copyTo( path, context );
|
copyTo( path, context );
|
||||||
|
|
|
@ -48,6 +48,16 @@ public interface SqmAttributeJoin<O,T> extends SqmQualifiedJoin<O,T>, JpaFetch<O
|
||||||
@Override
|
@Override
|
||||||
<S extends T> SqmAttributeJoin<O, S> treatAs(EntityDomainType<S> treatTarget);
|
<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
|
@deprecated not used anymore
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -489,7 +489,10 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( SqmRoot<?> root : roots ) {
|
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) {
|
private void validateFetchOwners(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner, SqmFrom<?, ?> joinContainer) {
|
||||||
for ( SqmJoin<?, ?> sqmJoin : owner.getSqmJoins() ) {
|
for ( SqmJoin<?, ?> sqmJoin : joinContainer.getSqmJoins() ) {
|
||||||
if ( sqmJoin instanceof SqmAttributeJoin<?, ?> ) {
|
if ( sqmJoin instanceof SqmAttributeJoin<?, ?> ) {
|
||||||
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmJoin;
|
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmJoin;
|
||||||
if ( attributeJoin.isFetched() ) {
|
if ( attributeJoin.isFetched() ) {
|
||||||
|
@ -541,19 +544,27 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validateFetchOwners( selectedFromSet, sqmJoin );
|
for ( SqmFrom<?, ?> sqmTreat : sqmJoin.getSqmTreats() ) {
|
||||||
}
|
if ( sqmTreat instanceof SqmAttributeJoin<?, ?> ) {
|
||||||
for ( SqmFrom<?, ?> sqmTreat : owner.getSqmTreats() ) {
|
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmTreat;
|
||||||
validateFetchOwners( selectedFromSet, 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 ) ) {
|
if ( !selectedFromSet.contains( owner ) ) {
|
||||||
throw new SemanticException(
|
throw new SemanticException(
|
||||||
"Query specified join fetching, but the owner " +
|
"Query specified join fetching, but the owner " +
|
||||||
"of the fetched association was not present in the select list " +
|
"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