HHH-18569 Don´t implicitly cast when using a subtype attribute name with Criteria API
This commit is contained in:
parent
c1cbbf1fd5
commit
1c87d73d2e
|
@ -12,7 +12,6 @@ import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
|
@ -87,11 +86,11 @@ public abstract class AbstractPluralAttribute<D, C, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
if ( CollectionPart.Nature.ELEMENT.getName().equals( name ) ) {
|
if ( CollectionPart.Nature.ELEMENT.getName().equals( name ) ) {
|
||||||
return elementPathSource;
|
return elementPathSource;
|
||||||
}
|
}
|
||||||
return elementPathSource.findSubPathSource( name, metamodel );
|
return elementPathSource.findSubPathSource( name, includeSubtypes );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
package org.hibernate.metamodel.model.domain.internal;
|
package org.hibernate.metamodel.model.domain.internal;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.sqm.SqmJoinable;
|
import org.hibernate.query.sqm.SqmJoinable;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
@ -42,8 +41,8 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
return getSqmPathType().findSubPathSource( name, metamodel );
|
return getSqmPathType().findSubPathSource( name, includeSubtypes );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -139,14 +139,13 @@ public class EntityTypeImpl<J>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name) {
|
public SqmPathSource<?> findSubPathSource(String name) {
|
||||||
final PersistentAttribute<? super J,?> attribute = findAttribute( name );
|
final PersistentAttribute<? super J,?> attribute = super.findAttribute( name );
|
||||||
if ( attribute != null ) {
|
if ( attribute != null ) {
|
||||||
return (SqmPathSource<?>) attribute;
|
return (SqmPathSource<?>) attribute;
|
||||||
}
|
}
|
||||||
else if ( EntityIdentifierMapping.matchesRoleName( name ) ) {
|
else if ( EntityIdentifierMapping.matchesRoleName( name ) ) {
|
||||||
return hasSingleIdAttribute() ? findIdAttribute() : getIdentifierDescriptor();
|
return hasSingleIdAttribute() ? findIdAttribute() : getIdentifierDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
|
else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
|
||||||
return discriminatorPathSource;
|
return discriminatorPathSource;
|
||||||
}
|
}
|
||||||
|
@ -156,18 +155,19 @@ public class EntityTypeImpl<J>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
final PersistentAttribute<? super J,?> attribute = super.findAttribute( name );
|
final PersistentAttribute<? super J,?> attribute = super.findAttribute( name );
|
||||||
if ( attribute != null ) {
|
if ( attribute != null ) {
|
||||||
return (SqmPathSource<?>) attribute;
|
return (SqmPathSource<?>) attribute;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//TODO: eliminate this cast!
|
if ( includeSubtypes ) {
|
||||||
final PersistentAttribute<?, ?> subtypeAttribute = findSubtypeAttribute( name );
|
final PersistentAttribute<?, ?> subtypeAttribute = findSubtypeAttribute( name );
|
||||||
if ( subtypeAttribute != null ) {
|
if ( subtypeAttribute != null ) {
|
||||||
return (SqmPathSource<?>) subtypeAttribute;
|
return (SqmPathSource<?>) subtypeAttribute;
|
||||||
}
|
}
|
||||||
else if ( EntityIdentifierMapping.matchesRoleName( name ) ) {
|
}
|
||||||
|
if ( EntityIdentifierMapping.matchesRoleName( name ) ) {
|
||||||
return hasSingleIdAttribute() ? findIdAttribute() : getIdentifierDescriptor();
|
return hasSingleIdAttribute() ? findIdAttribute() : getIdentifierDescriptor();
|
||||||
}
|
}
|
||||||
else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
|
else if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.metamodel.internal.MetadataContext;
|
import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
@ -60,7 +59,7 @@ public class ListAttributeImpl<X, E> extends AbstractPluralAttribute<X, List<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
||||||
if ( nature != null ) {
|
if ( nature != null ) {
|
||||||
switch ( nature ) {
|
switch ( nature ) {
|
||||||
|
@ -70,7 +69,7 @@ public class ListAttributeImpl<X, E> extends AbstractPluralAttribute<X, List<E>,
|
||||||
return getElementPathSource();
|
return getElementPathSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getElementPathSource().findSubPathSource( name, metamodel );
|
return getElementPathSource().findSubPathSource( name, includeSubtypes );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.metamodel.internal.MetadataContext;
|
import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
@ -70,7 +69,7 @@ public class MapAttributeImpl<X, K, V> extends AbstractPluralAttribute<X, Map<K,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name );
|
||||||
if ( nature != null ) {
|
if ( nature != null ) {
|
||||||
switch ( nature ) {
|
switch ( nature ) {
|
||||||
|
@ -80,7 +79,7 @@ public class MapAttributeImpl<X, K, V> extends AbstractPluralAttribute<X, Map<K,
|
||||||
return getElementPathSource();
|
return getElementPathSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getElementPathSource().findSubPathSource( name, metamodel );
|
return getElementPathSource().findSubPathSource( name, includeSubtypes );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,7 +14,6 @@ import org.hibernate.metamodel.model.domain.AnyMappingDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||||
|
@ -132,8 +131,8 @@ public class SingularAttributeImpl<D,J>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
return sqmPathSource.findSubPathSource( name, metamodel );
|
return sqmPathSource.findSubPathSource( name, includeSubtypes );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -145,7 +145,7 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
|
||||||
if ( pathRootByExposedNavigable != null ) {
|
if ( pathRootByExposedNavigable != null ) {
|
||||||
// identifier is an "unqualified attribute reference"
|
// identifier is an "unqualified attribute reference"
|
||||||
validateAsRoot( pathRootByExposedNavigable );
|
validateAsRoot( pathRootByExposedNavigable );
|
||||||
final SqmPath<?> sqmPath = pathRootByExposedNavigable.get( identifier );
|
final SqmPath<?> sqmPath = pathRootByExposedNavigable.get( identifier, true );
|
||||||
return isTerminal ? sqmPath : new DomainPathPart( sqmPath );
|
return isTerminal ? sqmPath : new DomainPathPart( sqmPath );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,10 +188,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
boolean allowReuse,
|
boolean allowReuse,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPathSource<?> subPathSource = lhs.getResolvedModel().getSubPathSource(
|
final SqmPathSource<?> subPathSource = lhs.getResolvedModel().getSubPathSource( name, true );
|
||||||
name,
|
|
||||||
creationState.getCreationContext().getJpaMetamodel()
|
|
||||||
);
|
|
||||||
if ( allowReuse ) {
|
if ( allowReuse ) {
|
||||||
if ( !isTerminal ) {
|
if ( !isTerminal ) {
|
||||||
for ( SqmJoin<?, ?> sqmJoin : lhs.getSqmJoins() ) {
|
for ( SqmJoin<?, ?> sqmJoin : lhs.getSqmJoins() ) {
|
||||||
|
|
|
@ -3587,7 +3587,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
+ "' of 'id()' is a '" + identifiableType.getTypeName()
|
+ "' of 'id()' is a '" + identifiableType.getTypeName()
|
||||||
+ "' and does not have a well-defined '@Id' attribute" );
|
+ "' and does not have a well-defined '@Id' attribute" );
|
||||||
}
|
}
|
||||||
return sqmPath.get( identifierDescriptor.getPathName() );
|
return sqmPath.get( identifierDescriptor.getPathName(), true );
|
||||||
}
|
}
|
||||||
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
|
||||||
return sqmPath.resolvePathPart( AnyKeyPart.KEY_NAME, true, processingStateStack.getCurrent().getCreationState() );
|
return sqmPath.resolvePathPart( AnyKeyPart.KEY_NAME, true, processingStateStack.getCurrent().getCreationState() );
|
||||||
|
|
|
@ -335,7 +335,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry {
|
||||||
|
|
||||||
private boolean definesAttribute(SqmPathSource<?> containerType, String name) {
|
private boolean definesAttribute(SqmPathSource<?> containerType, String name) {
|
||||||
return !( containerType.getSqmType() instanceof BasicDomainType )
|
return !( containerType.getSqmType() instanceof BasicDomainType )
|
||||||
&& containerType.findSubPathSource( name, getJpaMetamodel() ) != null;
|
&& containerType.findSubPathSource( name, true ) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JpaMetamodel getJpaMetamodel() {
|
private JpaMetamodel getJpaMetamodel() {
|
||||||
|
|
|
@ -42,8 +42,8 @@ public interface SqmPathSource<J> extends SqmExpressible<J>, Bindable<J>, SqmExp
|
||||||
/**
|
/**
|
||||||
* Find a {@link SqmPathSource} by name relative to this source.
|
* Find a {@link SqmPathSource} by name relative to this source.
|
||||||
*
|
*
|
||||||
|
* @param name the name of the path source to find
|
||||||
* @return null if the subPathSource is not found
|
* @return null if the subPathSource is not found
|
||||||
*
|
|
||||||
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
*/
|
*/
|
||||||
SqmPathSource<?> findSubPathSource(String name);
|
SqmPathSource<?> findSubPathSource(String name);
|
||||||
|
@ -52,16 +52,31 @@ public interface SqmPathSource<J> extends SqmExpressible<J>, Bindable<J>, SqmExp
|
||||||
* Find a {@link SqmPathSource} by name relative to this source.
|
* Find a {@link SqmPathSource} by name relative to this source.
|
||||||
*
|
*
|
||||||
* @return null if the subPathSource is not found
|
* @return null if the subPathSource is not found
|
||||||
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
|
* @deprecated Use {@link #findSubPathSource(String, boolean)} instead
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "7.0")
|
||||||
|
default SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
||||||
|
return findSubPathSource( name, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a {@link SqmPathSource} by name relative to this source. If {@code includeSubtypes} is set
|
||||||
|
* to {@code true} and this path source is polymorphic, also try finding subtype attributes.
|
||||||
*
|
*
|
||||||
|
* @param name the name of the path source to find
|
||||||
|
* @param includeSubtypes flag indicating whether to consider subtype attributes
|
||||||
|
* @return null if the subPathSource is not found
|
||||||
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
*/
|
*/
|
||||||
default SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
default SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
return findSubPathSource( name );
|
return findSubPathSource( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a {@link SqmPathSource} by name relative to this source.
|
* Find a {@link SqmPathSource} by name relative to this source.
|
||||||
*
|
*
|
||||||
|
* @param name the name of the path source to find
|
||||||
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
* @throws IllegalArgumentException if the subPathSource is not found
|
* @throws IllegalArgumentException if the subPathSource is not found
|
||||||
*/
|
*/
|
||||||
|
@ -81,13 +96,39 @@ public interface SqmPathSource<J> extends SqmExpressible<J>, Bindable<J>, SqmExp
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a {@link SqmPathSource} by name relative to this source.
|
* Find a {@link SqmPathSource} by name relative to this source and all its subtypes.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
* @throws IllegalArgumentException if the subPathSource is not found
|
* @throws IllegalArgumentException if the subPathSource is not found
|
||||||
|
* @deprecated Use #{@link #getSubPathSource(String, boolean)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "7.0")
|
||||||
default SqmPathSource<?> getSubPathSource(String name, JpaMetamodel metamodel) {
|
default SqmPathSource<?> getSubPathSource(String name, JpaMetamodel metamodel) {
|
||||||
final SqmPathSource<?> subPathSource = findSubPathSource( name, metamodel );
|
final SqmPathSource<?> subPathSource = findSubPathSource( name, true );
|
||||||
|
if ( subPathSource == null ) {
|
||||||
|
throw new PathElementException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Could not resolve attribute '%s' of '%s'",
|
||||||
|
name,
|
||||||
|
getExpressible().getTypeName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return subPathSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a {@link SqmPathSource} by name relative to this source. If {@code subtypes} is set
|
||||||
|
* to {@code true} and this path source is polymorphic, also try finding subtype attributes.
|
||||||
|
*
|
||||||
|
* @param name the name of the path source to find
|
||||||
|
* @param subtypes flag indicating whether to consider subtype attributes
|
||||||
|
* @throws IllegalStateException to indicate that this source cannot be de-referenced
|
||||||
|
* @throws IllegalArgumentException if the subPathSource is not found
|
||||||
|
*/
|
||||||
|
default SqmPathSource<?> getSubPathSource(String name, boolean subtypes) {
|
||||||
|
final SqmPathSource<?> subPathSource = findSubPathSource( name, true );
|
||||||
if ( subPathSource == null ) {
|
if ( subPathSource == null ) {
|
||||||
throw new PathElementException(
|
throw new PathElementException(
|
||||||
String.format(
|
String.format(
|
||||||
|
|
|
@ -196,7 +196,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
if ( resolvedPath != null ) {
|
if ( resolvedPath != null ) {
|
||||||
return resolvedPath;
|
return resolvedPath;
|
||||||
}
|
}
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
@ -417,8 +417,8 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X, Y> SqmAttributeJoin<X, Y> join(String attributeName, JoinType jt) {
|
public <X, Y> SqmAttributeJoin<X, Y> join(String attributeName, JoinType jt) {
|
||||||
final SqmPathSource<?> subPathSource =
|
final SqmPathSource<Y> subPathSource = (SqmPathSource<Y>) getReferencedPathSource()
|
||||||
getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
.getSubPathSource( attributeName );
|
||||||
return (SqmAttributeJoin<X, Y>) buildJoin( subPathSource, SqmJoinType.from( jt ), false );
|
return (SqmAttributeJoin<X, Y>) buildJoin( subPathSource, SqmJoinType.from( jt ), false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,8 +430,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X, Y> SqmBagJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
|
public <X, Y> SqmBagJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
|
||||||
final SqmPathSource<?> joinedPathSource =
|
final SqmPathSource<?> joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName );
|
||||||
getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
|
||||||
|
|
||||||
if ( joinedPathSource instanceof BagPersistentAttribute ) {
|
if ( joinedPathSource instanceof BagPersistentAttribute ) {
|
||||||
final SqmBagJoin<T, Y> join = buildBagJoin(
|
final SqmBagJoin<T, Y> join = buildBagJoin(
|
||||||
|
@ -462,8 +461,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X, Y> SqmSetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
|
public <X, Y> SqmSetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
|
||||||
final SqmPathSource<?> joinedPathSource =
|
final SqmPathSource<?> joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName );
|
||||||
getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
|
||||||
|
|
||||||
if ( joinedPathSource instanceof SetPersistentAttribute ) {
|
if ( joinedPathSource instanceof SetPersistentAttribute ) {
|
||||||
final SqmSetJoin<T, Y> join = buildSetJoin(
|
final SqmSetJoin<T, Y> join = buildSetJoin(
|
||||||
|
@ -494,8 +492,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X, Y> SqmListJoin<X, Y> joinList(String attributeName, JoinType jt) {
|
public <X, Y> SqmListJoin<X, Y> joinList(String attributeName, JoinType jt) {
|
||||||
final SqmPathSource<?> joinedPathSource =
|
final SqmPathSource<?> joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName );
|
||||||
getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
|
||||||
|
|
||||||
if ( joinedPathSource instanceof ListPersistentAttribute ) {
|
if ( joinedPathSource instanceof ListPersistentAttribute ) {
|
||||||
final SqmListJoin<T, Y> join = buildListJoin(
|
final SqmListJoin<T, Y> join = buildListJoin(
|
||||||
|
@ -526,8 +523,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X, K, V> SqmMapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
|
public <X, K, V> SqmMapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
|
||||||
final SqmPathSource<?> joinedPathSource =
|
final SqmPathSource<?> joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName );
|
||||||
getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
|
||||||
|
|
||||||
if ( joinedPathSource instanceof MapPersistentAttribute<?, ?, ?> ) {
|
if ( joinedPathSource instanceof MapPersistentAttribute<?, ?, ?> ) {
|
||||||
final SqmMapJoin<T, K, V> join = buildMapJoin(
|
final SqmMapJoin<T, K, V> join = buildMapJoin(
|
||||||
|
|
|
@ -193,11 +193,18 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
||||||
@Override
|
@Override
|
||||||
public <Y> SqmPath<Y> get(String attributeName) {
|
public <Y> SqmPath<Y> get(String attributeName) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final SqmPathSource<Y> subNavigable = (SqmPathSource<Y>)
|
final SqmPathSource<Y> subNavigable = (SqmPathSource<Y>) getResolvedModel().getSubPathSource( attributeName );
|
||||||
getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
|
|
||||||
return resolvePath( attributeName, subNavigable );
|
return resolvePath( attributeName, subNavigable );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <Y> SqmPath<Y> get(String attributeName, boolean includeSubtypes) {
|
||||||
|
//noinspection unchecked
|
||||||
|
final SqmPathSource<Y> subPathSource = (SqmPathSource<Y>)
|
||||||
|
getResolvedModel().getSubPathSource( attributeName, includeSubtypes );
|
||||||
|
return resolvePath( attributeName, subPathSource );
|
||||||
|
}
|
||||||
|
|
||||||
protected <X> SqmPath<X> resolvePath(PersistentAttribute<?, X> attribute) {
|
protected <X> SqmPath<X> resolvePath(PersistentAttribute<?, X> attribute) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return resolvePath( attribute.getName(), (SqmPathSource<X>) attribute );
|
return resolvePath( attribute.getName(), (SqmPathSource<X>) attribute );
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class SqmElementAggregateFunction<T> extends AbstractSqmSpecificPluralPar
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class SqmEmbeddedValuedSimplePath<T>
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class SqmFkExpression<T> extends AbstractSqmPath<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
|
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class SqmFunctionPath<T> extends AbstractSqmPath<T> {
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class SqmIndexAggregateFunction<T> extends AbstractSqmSpecificPluralPartP
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,6 +175,16 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
||||||
@Override
|
@Override
|
||||||
<Y> SqmPath<Y> get(String attributeName);
|
<Y> SqmPath<Y> get(String attributeName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #get(String)}, but if {@code includeSubtypes} is set to {@code true}
|
||||||
|
* and this path is polymorphic, also try finding subtype attributes.
|
||||||
|
*
|
||||||
|
* @see SqmPathSource#findSubPathSource(String, boolean)
|
||||||
|
*/
|
||||||
|
default <Y> SqmPath<Y> get(String attributeName, boolean includeSubtypes) {
|
||||||
|
return get( attributeName );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
SqmPath<T> copy(SqmCopyContext context);
|
SqmPath<T> copy(SqmCopyContext context);
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
||||||
+ "' refers to a collection and so element attribute '" + name
|
+ "' refers to a collection and so element attribute '" + name
|
||||||
+ "' may not be referenced directly (use element() function)" );
|
+ "' may not be referenced directly (use element() function)" );
|
||||||
}
|
}
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,9 @@ import org.hibernate.query.criteria.JpaSetJoin;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
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.SqmFrom;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.Expression;
|
import jakarta.persistence.criteria.Expression;
|
||||||
import jakarta.persistence.criteria.JoinType;
|
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,11 +155,4 @@ public class SqmSetJoin<O, E>
|
||||||
}
|
}
|
||||||
return treat;
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <X, Y> SqmAttributeJoin<X, Y> fetch(String attributeName) {
|
|
||||||
return fetch( attributeName, JoinType.INNER);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class SqmTreatedEmbeddedValuedSimplePath<T, S extends T> extends SqmEmbed
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
|
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class SqmTreatedRoot extends SqmRoot implements SqmTreatedFrom {
|
||||||
String name,
|
String name,
|
||||||
boolean isTerminal,
|
boolean isTerminal,
|
||||||
SqmCreationState creationState) {
|
SqmCreationState creationState) {
|
||||||
final SqmPath<?> sqmPath = get( name );
|
final SqmPath<?> sqmPath = get( name, true );
|
||||||
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
return sqmPath;
|
return sqmPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,9 +494,9 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( SqmRoot<?> root : roots ) {
|
for ( SqmRoot<?> root : roots ) {
|
||||||
validateFetchOwners( selectedFromSet, root, root );
|
validateFetchOwners( selectedFromSet, root );
|
||||||
for ( SqmFrom<?, ?> sqmTreat : root.getSqmTreats() ) {
|
for ( SqmFrom<?, ?> sqmTreat : root.getSqmTreats() ) {
|
||||||
validateFetchOwners( selectedFromSet, root, sqmTreat );
|
validateFetchOwners( selectedFromSet, sqmTreat );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,12 +543,12 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateFetchOwners(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> owner, SqmFrom<?, ?> joinContainer) {
|
private void validateFetchOwners(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> joinContainer) {
|
||||||
for ( SqmJoin<?, ?> sqmJoin : joinContainer.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() ) {
|
||||||
assertFetchOwner( selectedFromSet, owner, sqmJoin );
|
assertFetchOwner( selectedFromSet, attributeJoin.getLhs(), sqmJoin );
|
||||||
// Only need to check the first level
|
// Only need to check the first level
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -557,14 +557,14 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
if ( sqmTreat instanceof SqmAttributeJoin<?, ?> ) {
|
if ( sqmTreat instanceof SqmAttributeJoin<?, ?> ) {
|
||||||
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmTreat;
|
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmTreat;
|
||||||
if ( attributeJoin.isFetched() ) {
|
if ( attributeJoin.isFetched() ) {
|
||||||
assertFetchOwner( selectedFromSet, owner, attributeJoin );
|
assertFetchOwner( selectedFromSet, attributeJoin.getLhs(), attributeJoin );
|
||||||
// Only need to check the first level
|
// Only need to check the first level
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validateFetchOwners( selectedFromSet, sqmJoin, sqmTreat );
|
validateFetchOwners( selectedFromSet, sqmTreat );
|
||||||
}
|
}
|
||||||
validateFetchOwners( selectedFromSet, sqmJoin, sqmJoin );
|
validateFetchOwners( selectedFromSet, sqmJoin );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,6 @@ public class TreatedSubclassSameTypeTest {
|
||||||
executeQuery( scope, criteria -> criteria.from( MyEntity1.class ), true );
|
executeQuery( scope, criteria -> criteria.from( MyEntity1.class ), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoin(SessionFactoryScope scope) {
|
|
||||||
executeQuery( scope, criteria -> criteria.from( MyEntity1.class ), false );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJoinOnTreatedSubtype(SessionFactoryScope scope) {
|
public void testJoinOnTreatedSubtype(SessionFactoryScope scope) {
|
||||||
executeQuery( scope, criteria -> criteria.from( MySubEntity1.class ), true );
|
executeQuery( scope, criteria -> criteria.from( MySubEntity1.class ), true );
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class JoinedSubclassTest {
|
||||||
|
|
||||||
Root<Person> root = criteria.from( Person.class );
|
Root<Person> root = criteria.from( Person.class );
|
||||||
|
|
||||||
criteria.where( criteriaBuilder.gt( root.get( "salary" ), new BigDecimal( 100 ) ) );
|
criteria.where( criteriaBuilder.gt( criteriaBuilder.treat( root, Employee.class ).get( "salary" ), new BigDecimal( 100 ) ) );
|
||||||
|
|
||||||
result = s.createQuery( criteria ).list();
|
result = s.createQuery( criteria ).list();
|
||||||
// result = s.createCriteria( Person.class )
|
// result = s.createCriteria( Person.class )
|
||||||
|
|
|
@ -99,12 +99,15 @@ public class CorrelatedPluralJoinInheritanceTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImplicitTreat(EntityManagerFactoryScope scope) {
|
public void testExplicitTreat(EntityManagerFactoryScope scope) {
|
||||||
scope.inTransaction( entityManager -> {
|
scope.inTransaction( entityManager -> {
|
||||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||||
final CriteriaQuery<ContinuousData> criteriaQuery = cb.createQuery( ContinuousData.class );
|
final CriteriaQuery<ContinuousData> criteriaQuery = cb.createQuery( ContinuousData.class );
|
||||||
final Root<ContinuousData> root = criteriaQuery.from( ContinuousData.class );
|
final Root<ContinuousData> root = criteriaQuery.from( ContinuousData.class );
|
||||||
criteriaQuery.where( createExistsPredicate( root, criteriaQuery, cb, "storedTags" ) );
|
final Subquery<String> subquery = criteriaQuery.subquery( String.class );
|
||||||
|
final Root<ContinuousData> root2 = subquery.correlate( root );
|
||||||
|
subquery.select( root2.get( "id" ) ).where( cb.treat( root2, StoredContinuousData.class ).join( "storedTags" ).get( "id" ).in( "a", "b" ) );
|
||||||
|
criteriaQuery.where( cb.exists( subquery ) );
|
||||||
final List<ContinuousData> resultList = entityManager.createQuery( criteriaQuery ).getResultList();
|
final List<ContinuousData> resultList = entityManager.createQuery( criteriaQuery ).getResultList();
|
||||||
assertThat( resultList ).hasSize( 1 );
|
assertThat( resultList ).hasSize( 1 );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class DiscriminatorTest {
|
||||||
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
||||||
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
||||||
Root<Person> root = criteria.from( Person.class );
|
Root<Person> root = criteria.from( Person.class );
|
||||||
criteria.where( criteriaBuilder.gt( root.get( "salary" ), new BigDecimal( 100 ) ) );
|
criteria.where( criteriaBuilder.gt( criteriaBuilder.treat( root, Employee.class ).get( "salary" ), new BigDecimal( 100 ) ) );
|
||||||
result = s.createQuery( criteria ).list();
|
result = s.createQuery( criteria ).list();
|
||||||
// result = s.createCriteria(Person.class)
|
// result = s.createCriteria(Person.class)
|
||||||
// .add( Property.forName( "salary").gt( new BigDecimal( 100) ) )
|
// .add( Property.forName( "salary").gt( new BigDecimal( 100) ) )
|
||||||
|
|
|
@ -182,7 +182,7 @@ public class SimpleInheritanceTest {
|
||||||
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
||||||
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
||||||
Root<Person> root = criteria.from( Person.class );
|
Root<Person> root = criteria.from( Person.class );
|
||||||
criteria.where( criteriaBuilder.gt( root.get( "salary" ), new BigDecimal( 100 ) ) );
|
criteria.where( criteriaBuilder.gt( criteriaBuilder.treat( root, Employee.class ).get( "salary" ), new BigDecimal( 100 ) ) );
|
||||||
|
|
||||||
result = s.createQuery( criteria ).list();
|
result = s.createQuery( criteria ).list();
|
||||||
// result = s.createCriteria( Person.class )
|
// result = s.createCriteria( Person.class )
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class CriteriaInheritanceJoinTest {
|
||||||
final CriteriaBuilder cb = session.getCriteriaBuilder();
|
final CriteriaBuilder cb = session.getCriteriaBuilder();
|
||||||
final CriteriaQuery<Address> cq = cb.createQuery( Address.class );
|
final CriteriaQuery<Address> cq = cb.createQuery( Address.class );
|
||||||
final Root<Address> addressRoot = cq.from( Address.class );
|
final Root<Address> addressRoot = cq.from( Address.class );
|
||||||
final Join<Address, Street> join = addressRoot.join( "street" );
|
final Join<Address, Street> join = cb.treat( addressRoot, StreetAddress.class ).join( "street" );
|
||||||
cq.select( addressRoot ).where( cb.equal( join.get( "name" ), "Via Roma" ) );
|
cq.select( addressRoot ).where( cb.equal( join.get( "name" ), "Via Roma" ) );
|
||||||
final Address result = session.createQuery( cq ).getSingleResult();
|
final Address result = session.createQuery( cq ).getSingleResult();
|
||||||
assertThat( result ).isInstanceOf( StreetAddress.class );
|
assertThat( result ).isInstanceOf( StreetAddress.class );
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class UnionSubclassTest {
|
||||||
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
|
||||||
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
CriteriaQuery<Person> criteria = criteriaBuilder.createQuery( Person.class );
|
||||||
Root<Person> root = criteria.from( Person.class );
|
Root<Person> root = criteria.from( Person.class );
|
||||||
criteria.where( criteriaBuilder.gt( root.get( "salary" ), new BigDecimal( 100 ) ) );
|
criteria.where( criteriaBuilder.gt( criteriaBuilder.treat( root, Employee.class ).get( "salary" ), new BigDecimal( 100 ) ) );
|
||||||
|
|
||||||
result = s.createQuery( criteria ).list();
|
result = s.createQuery( criteria ).list();
|
||||||
|
|
||||||
|
|
|
@ -376,6 +376,13 @@ In Hibernate 7, the configuration property `hibernate.jdbc.batch_size` now has n
|
||||||
Automatic batching may be enabled by explicitly calling `setJdbcBatchSize()`.
|
Automatic batching may be enabled by explicitly calling `setJdbcBatchSize()`.
|
||||||
However, the preferred approach is to explicitly batch operations via `insertMultiple()`, `updateMultiple()`, or `deleteMultiple()`.
|
However, the preferred approach is to explicitly batch operations via `insertMultiple()`, `updateMultiple()`, or `deleteMultiple()`.
|
||||||
|
|
||||||
|
[[criteria-implicit-treat]]
|
||||||
|
== Criteria API and inheritance subtypes attributes
|
||||||
|
|
||||||
|
It was previously possible to use the string version of the `jakarta.persistence.criteria.Path#get` and `jakarta.persistence.criteria.From#join` methods with names of attributes defined in an inheritance subtype of the type represented by the path expression. This was handled internally by implicitly treating the path as the subtype which defines said attribute. Since Hibernate 7.0, aligning with the JPA specification, the Criteria API will no longer allow retrieving subtype attributes this way, and it's going to require an explicit `jakarta.persistence.criteria.CriteriaBuilder#treat` to be called on the path first to downcast it to the subtype which defines the attribute.
|
||||||
|
|
||||||
|
Implicit treats are still going to be applied when an HQL query dereferences a path belonging to an inheritance subtype.
|
||||||
|
|
||||||
[[hbm-transform]]
|
[[hbm-transform]]
|
||||||
== hbm.xml Transformation
|
== hbm.xml Transformation
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,6 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
|
@ -973,14 +972,14 @@ public abstract class MockSessionFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodel metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name, boolean includeSubtypes) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case EntityIdentifierMapping.ID_ROLE_NAME:
|
case EntityIdentifierMapping.ID_ROLE_NAME:
|
||||||
return getIdentifierDescriptor();
|
return getIdentifierDescriptor();
|
||||||
case "{version}":
|
case "{version}":
|
||||||
return findVersionAttribute();
|
return findVersionAttribute();
|
||||||
}
|
}
|
||||||
final SqmPathSource<?> source = super.findSubPathSource(name, metamodel);
|
final SqmPathSource<?> source = super.findSubPathSource(name, includeSubtypes);
|
||||||
if ( source != null ) {
|
if ( source != null ) {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue