HHH-15802 SubQuery with 'in' results in java.lang.ClassCastException class org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl cannot be cast to class org.hibernate.metamodel.mapping.EntityValuedModelPart
This commit is contained in:
parent
e896656bb3
commit
8f78e4e23b
|
@ -81,7 +81,7 @@ public class InferredBasicValueResolver {
|
|||
typeConfiguration
|
||||
);
|
||||
}
|
||||
else if ( explicitJavaType instanceof TemporalJavaType ) {
|
||||
else if ( explicitJavaType.isTemporalType() ) {
|
||||
return fromTemporal(
|
||||
(TemporalJavaType<T>) explicitJavaType,
|
||||
null,
|
||||
|
@ -133,7 +133,7 @@ public class InferredBasicValueResolver {
|
|||
typeConfiguration
|
||||
);
|
||||
}
|
||||
else if ( reflectedJtd instanceof TemporalJavaType ) {
|
||||
else if ( reflectedJtd.isTemporalType() ) {
|
||||
return fromTemporal(
|
||||
(TemporalJavaType<T>) reflectedJtd,
|
||||
null,
|
||||
|
@ -170,7 +170,7 @@ public class InferredBasicValueResolver {
|
|||
);
|
||||
registeredElementType = resolution.getLegacyResolvedBasicType();
|
||||
}
|
||||
else if ( elementJtd instanceof TemporalJavaType ) {
|
||||
else if ( elementJtd.isTemporalType() ) {
|
||||
final InferredBasicValueResolution resolution = InferredBasicValueResolver.fromTemporal(
|
||||
(TemporalJavaType<T>) elementJtd,
|
||||
null,
|
||||
|
@ -492,7 +492,7 @@ public class InferredBasicValueResolver {
|
|||
// Case #1 - explicit JavaType
|
||||
|
||||
if ( explicitJavaType != null ) {
|
||||
if ( !(explicitJavaType instanceof TemporalJavaType) ) {
|
||||
if ( !explicitJavaType.isTemporalType() ) {
|
||||
throw new MappingException(
|
||||
"Explicit JavaType [" + explicitJavaType +
|
||||
"] defined for temporal value must implement TemporalJavaType"
|
||||
|
|
|
@ -47,4 +47,9 @@ public interface PluralPersistentAttribute<D, C, E>
|
|||
"Plural attribute [" + getPathName() + "] is not indexed (list / map)"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean checkTypeComparability() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,4 +28,8 @@ public interface TupleType<J> extends SqmExpressible<J> {
|
|||
SqmExpressible<?> get(int index);
|
||||
SqmExpressible<?> get(String componentName);
|
||||
|
||||
@Override
|
||||
default boolean checkTypeComparability() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,4 +60,9 @@ public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
|||
public Class<D> getJavaType() {
|
||||
return getExpressibleJavaType().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTypeComparability() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ import org.hibernate.query.sqm.function.NamedSqmFunctionDescriptor;
|
|||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.internal.ParameterCollector;
|
||||
import org.hibernate.query.sqm.internal.SqmCreationProcessingStateImpl;
|
||||
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||
import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState;
|
||||
import org.hibernate.query.sqm.internal.SqmQueryPartCreationProcessingStateStandardImpl;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
|
@ -2463,6 +2464,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
break;
|
||||
}
|
||||
}
|
||||
((SqmCriteriaNodeBuilder) creationContext.getNodeBuilder()).assertComparable( left, right );
|
||||
return new SqmComparisonPredicate(
|
||||
left,
|
||||
comparisonOperator,
|
||||
|
|
|
@ -41,7 +41,7 @@ public class BindingTypeHelper {
|
|||
SessionFactoryImplementor sessionFactory) {
|
||||
if ( precision != null ) {
|
||||
final SqmExpressible<T> sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory );
|
||||
if ( !( sqmExpressible.getExpressibleJavaType() instanceof TemporalJavaType ) ) {
|
||||
if ( !( sqmExpressible.getExpressibleJavaType().isTemporalType() ) ) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot treat non-temporal parameter type with temporal precision"
|
||||
);
|
||||
|
@ -64,7 +64,7 @@ public class BindingTypeHelper {
|
|||
Object value,
|
||||
JdbcMapping baseType,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( value == null || !( baseType.getJdbcJavaType() instanceof TemporalJavaType<?> ) ) {
|
||||
if ( value == null || !baseType.getJdbcJavaType().isTemporalType() ) {
|
||||
return baseType;
|
||||
}
|
||||
|
||||
|
|
|
@ -290,7 +290,7 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
}
|
||||
|
||||
private void setExplicitTemporalPrecision(TemporalType temporalTypePrecision) {
|
||||
if ( bindType == null || determineJavaType( bindType ) instanceof TemporalJavaType<?> ) {
|
||||
if ( bindType == null || determineJavaType( bindType ).isTemporalType() ) {
|
||||
this.bindType = BindingTypeHelper.INSTANCE.resolveTemporalPrecision(
|
||||
temporalTypePrecision,
|
||||
bindType,
|
||||
|
|
|
@ -34,4 +34,8 @@ public interface SqmExpressible<J> extends BindableType<J> {
|
|||
default SqmExpressible<J> resolveExpressible(SessionFactoryImplementor sessionFactory) {
|
||||
return this;
|
||||
}
|
||||
|
||||
default boolean checkTypeComparability(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.TupleType;
|
||||
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.query.BindableType;
|
||||
|
@ -231,6 +234,42 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
return sessionFactory.get();
|
||||
}
|
||||
|
||||
public boolean areTypesComparable(SqmExpressible<?> lhsType, SqmExpressible<?> rhsType) {
|
||||
if ( lhsType == null || rhsType == null || lhsType == rhsType ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !lhsType.checkTypeComparability() || !rhsType.checkTypeComparability() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final JavaType<?> lhsJavaType = lhsType.getExpressibleJavaType();
|
||||
final JavaType<?> rhsJavaType = rhsType.getExpressibleJavaType();
|
||||
|
||||
if ( lhsJavaType.isTemporalType() || rhsJavaType.isTemporalType() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( lhsJavaType.isUnknownType() || rhsJavaType.isUnknownType() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( lhsJavaType == rhsJavaType
|
||||
|| lhsJavaType.isWider( rhsJavaType )
|
||||
|| rhsJavaType.isWider( lhsJavaType ) ) {
|
||||
// Assume we can coerce one to another
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( lhsJavaType.getJavaTypeClass().isAssignableFrom( rhsJavaType.getJavaTypeClass() )
|
||||
|| rhsJavaType.getJavaTypeClass().isAssignableFrom( lhsJavaType.getJavaTypeClass() ) ) {
|
||||
// Polymorphic entity comparison
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicType<Boolean> getBooleanType() {
|
||||
final BasicType<Boolean> booleanType = this.booleanType;
|
||||
|
@ -1253,6 +1292,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
public Class<T> getBindableJavaType() {
|
||||
return javaType.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTypeComparability() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1996,6 +2040,8 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Expression<? extends Y> lower, Expression<? extends Y> upper) {
|
||||
assertComparable( value, lower );
|
||||
assertComparable( value, upper );
|
||||
//noinspection unchecked
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression<? extends Y>) value,
|
||||
|
@ -2010,17 +2056,36 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@SuppressWarnings("unchecked")
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Y lower, Y upper) {
|
||||
final SqmExpression<? extends Y> valueExpression = (SqmExpression<? extends Y>) value;
|
||||
final SqmExpression<?> lowerExpr = value( lower, valueExpression );
|
||||
final SqmExpression<?> upperExpr = value( upper, valueExpression );
|
||||
assertComparable( valueExpression, lowerExpr );
|
||||
assertComparable( valueExpression, upperExpr );
|
||||
return new SqmBetweenPredicate(
|
||||
valueExpression,
|
||||
value( lower, valueExpression ),
|
||||
value( upper, valueExpression ),
|
||||
lowerExpr,
|
||||
upperExpr,
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
public void assertComparable(Expression<?> x, Expression<?> y) {
|
||||
final SqmExpressible<?> lhsType = ((SqmExpression<?>) x).getNodeType();
|
||||
final SqmExpressible<?> rhsType = ((SqmExpression<?>) y).getNodeType();
|
||||
if ( !areTypesComparable( lhsType, rhsType ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Can't compare test expression of type [%s] with element of type [%s]",
|
||||
lhsType,
|
||||
rhsType
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate equal(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.EQUAL,
|
||||
|
@ -2031,16 +2096,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate equal(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.EQUAL,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notEqual(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_EQUAL,
|
||||
|
@ -2051,16 +2119,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate notEqual(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_EQUAL,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
|
@ -2071,16 +2142,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
|
@ -2091,16 +2165,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2112,16 +2189,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
value( y, (SqmExpression) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2133,16 +2213,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
value( y, (SqmExpression) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThan(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2153,10 +2236,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThan(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
@ -2173,16 +2258,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate gt(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2193,16 +2281,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate gt(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate ge(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2213,16 +2304,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate ge(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate lt(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2233,16 +2327,19 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate lt(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate le(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
|
@ -2253,10 +2350,12 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate le(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
value( y, (SqmExpression<?>) x ),
|
||||
yExpr,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6061,7 +6061,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
private static Expression getActualExpression(Expression expression) {
|
||||
if ( expression.getExpressionType() instanceof EmbeddableValuedModelPart ) {
|
||||
final EmbeddableValuedModelPart embeddableValuedModelPart = (EmbeddableValuedModelPart) expression.getExpressionType();
|
||||
if ( embeddableValuedModelPart.getJavaType() instanceof TemporalJavaType<?> ) {
|
||||
if ( embeddableValuedModelPart.getJavaType().isTemporalType() ) {
|
||||
return ( (SqlTupleContainer) expression ).getSqlTuple().getExpressions().get( 0 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public class SqmExpressionHelper {
|
|||
public static boolean isCompositeTemporal(SqmExpression<?> expression) {
|
||||
// When TimeZoneStorageStrategy.COLUMN is used, that implies using a composite user type
|
||||
return expression instanceof SqmPath<?> && expression.getNodeType() instanceof EmbeddedSqmPathSource<?>
|
||||
&& expression.getJavaTypeDescriptor() instanceof TemporalJavaType<?>;
|
||||
&& expression.getJavaTypeDescriptor().isTemporalType();
|
||||
}
|
||||
|
||||
public static SqmExpression<?> getActualExpression(SqmExpression<?> expression) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.query.criteria.JpaExpression;
|
|||
import org.hibernate.query.internal.QueryHelper;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
|
@ -134,11 +135,9 @@ public class SqmInListPredicate<T> extends AbstractNegatableSqmPredicate impleme
|
|||
}
|
||||
|
||||
private void implyListElementType(SqmExpression<?> expression) {
|
||||
nodeBuilder().assertComparable( getTestExpression(), expression );
|
||||
expression.applyInferableType(
|
||||
QueryHelper.highestPrecedenceType2(
|
||||
getTestExpression().getNodeType(),
|
||||
expression.getNodeType()
|
||||
)
|
||||
QueryHelper.highestPrecedenceType2( getTestExpression().getNodeType(), expression.getNodeType() )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,12 @@ import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
|
|||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.criteria.AbstractQuery;
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Selection;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import jakarta.persistence.metamodel.EntityType;
|
||||
|
||||
|
@ -373,4 +375,37 @@ public abstract class AbstractSqmSelectQuery<T>
|
|||
}
|
||||
sqmQueryPart.appendHqlString( sb );
|
||||
}
|
||||
|
||||
protected Selection<? extends T> getResultSelection(Selection<?>[] selections) {
|
||||
final Selection<? extends T> resultSelection;
|
||||
Class<T> resultType = getResultType();
|
||||
if ( resultType == null || resultType == Object.class ) {
|
||||
switch ( selections.length ) {
|
||||
case 0: {
|
||||
throw new IllegalArgumentException(
|
||||
"empty selections passed to criteria query typed as Object"
|
||||
);
|
||||
}
|
||||
case 1: {
|
||||
resultSelection = ( Selection<? extends T> ) selections[0];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setResultType( (Class<T>) Object[].class );
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().array( selections );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( Tuple.class.isAssignableFrom( resultType ) ) {
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().tuple( selections );
|
||||
}
|
||||
else if ( resultType.isArray() ) {
|
||||
resultSelection = nodeBuilder().array( resultType, selections );
|
||||
}
|
||||
else {
|
||||
resultSelection = nodeBuilder().construct( resultType, selections );
|
||||
}
|
||||
return resultSelection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -277,34 +277,7 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
|
|||
}
|
||||
}
|
||||
|
||||
final Selection<? extends T> resultSelection;
|
||||
Class<T> resultType = getResultType();
|
||||
if ( resultType == null || resultType == Object.class ) {
|
||||
switch ( selections.length ) {
|
||||
case 0: {
|
||||
throw new IllegalArgumentException(
|
||||
"empty selections passed to criteria query typed as Object"
|
||||
);
|
||||
}
|
||||
case 1: {
|
||||
resultSelection = ( Selection<? extends T> ) selections[0];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setResultType( (Class<T>) Object[].class );
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().array( selections );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( Tuple.class.isAssignableFrom( resultType ) ) {
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().tuple( selections );
|
||||
}
|
||||
else if ( resultType.isArray() ) {
|
||||
resultSelection = nodeBuilder().array( resultType, selections );
|
||||
}
|
||||
else {
|
||||
resultSelection = nodeBuilder().construct( resultType, selections );
|
||||
}
|
||||
final Selection<? extends T> resultSelection = getResultSelection( selections );
|
||||
getQuerySpec().getSelectClause().setSelection( (SqmSelectableNode<?>) resultSelection );
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.criteria.JpaCteContainer;
|
||||
import org.hibernate.query.criteria.JpaCteCriteria;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
|
@ -51,6 +52,7 @@ import org.hibernate.query.sqm.tree.from.SqmJoin;
|
|||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
import jakarta.persistence.Tuple;
|
||||
|
@ -83,6 +85,7 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
NodeBuilder builder) {
|
||||
super( queryPart, resultType, builder );
|
||||
this.parent = parent;
|
||||
applyInferableType( resultType );
|
||||
}
|
||||
|
||||
public SqmSubQuery(
|
||||
|
@ -94,6 +97,7 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
super( builder, cteStatements, resultType );
|
||||
this.parent = parent;
|
||||
setQueryPart( queryPart );
|
||||
applyInferableType( resultType );
|
||||
}
|
||||
|
||||
public SqmSubQuery(
|
||||
|
@ -102,6 +106,7 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
NodeBuilder builder) {
|
||||
super( resultType, builder );
|
||||
this.parent = parent;
|
||||
applyInferableType( resultType );
|
||||
}
|
||||
|
||||
public SqmSubQuery(
|
||||
|
@ -197,6 +202,7 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
}
|
||||
//noinspection unchecked
|
||||
querySpec.setSelection( (JpaSelection<T>) expression );
|
||||
// applyInferableType( (Class<T>) querySpec.getSelection().getJavaType() );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -205,34 +211,8 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
public SqmSubQuery<T> multiselect(Selection<?>... selections) {
|
||||
validateComplianceMultiselect();
|
||||
|
||||
final Selection<? extends T> resultSelection;
|
||||
Class<T> resultType = getResultType();
|
||||
if ( resultType == null || resultType == Object.class ) {
|
||||
switch ( selections.length ) {
|
||||
case 0: {
|
||||
throw new IllegalArgumentException(
|
||||
"empty selections passed to criteria query typed as Object"
|
||||
);
|
||||
}
|
||||
case 1: {
|
||||
resultSelection = ( Selection<? extends T> ) selections[0];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setResultType( (Class<T>) Object[].class );
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().array( selections );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( Tuple.class.isAssignableFrom( resultType ) ) {
|
||||
resultSelection = ( Selection<? extends T> ) nodeBuilder().tuple( selections );
|
||||
}
|
||||
else if ( resultType.isArray() ) {
|
||||
resultSelection = nodeBuilder().array( resultType, selections );
|
||||
}
|
||||
else {
|
||||
resultSelection = nodeBuilder().construct( resultType, selections );
|
||||
}
|
||||
final Selection<? extends T> resultSelection = getResultSelection( selections );
|
||||
|
||||
final SqmQuerySpec<T> querySpec = getQuerySpec();
|
||||
if ( querySpec.getSelectClause() == null ) {
|
||||
querySpec.setSelectClause( new SqmSelectClause( false, 1, nodeBuilder() ) );
|
||||
|
@ -603,6 +583,18 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
setResultType( type == null ? null : expressibleType.getExpressibleJavaType().getJavaTypeClass() );
|
||||
}
|
||||
|
||||
private void applyInferableType(Class<T> type) {
|
||||
final EntityDomainType<T> entityDescriptor = nodeBuilder().getSessionFactory().getRuntimeMetamodels()
|
||||
.getJpaMetamodel()
|
||||
.findEntityType( type );
|
||||
if ( entityDescriptor != null ) {
|
||||
this.expressibleType = entityDescriptor;
|
||||
}
|
||||
else {
|
||||
this.expressibleType = nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType( type );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Long> asLong() {
|
||||
return castAs( nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType( Long.class ) );
|
||||
|
|
|
@ -61,4 +61,13 @@ public class CurrencyJavaType extends AbstractClassJavaType<Currency> {
|
|||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWider(JavaType<?> javaType) {
|
||||
switch ( javaType.getJavaType().getTypeName() ) {
|
||||
case "java.lang.String":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,4 +227,23 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
}
|
||||
return Enum.valueOf( getJavaTypeClass(), relationalForm.trim() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWider(JavaType<?> javaType) {
|
||||
switch ( javaType.getJavaType().getTypeName() ) {
|
||||
case "byte":
|
||||
case "java.lang.Byte":
|
||||
case "short":
|
||||
case "java.lang.Short":
|
||||
case "int":
|
||||
case "java.lang.Integer":
|
||||
case "long":
|
||||
case "java.lang.Long":
|
||||
case "java.lang.String":
|
||||
case "java.lang.Character":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -323,4 +324,22 @@ public interface JavaType<T> extends Serializable {
|
|||
return createJavaType( parameterizedType );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the implementation is an instance of {@link TemporalJavaType}
|
||||
*
|
||||
* @return true if it is an instance of {@link TemporalJavaType}; false otherwise
|
||||
*/
|
||||
default boolean isTemporalType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the implementation is an instance of {@link org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType}
|
||||
*
|
||||
* @return true if it is an instance of {@link UnknownBasicJavaType}; false otherwise
|
||||
*/
|
||||
default boolean isUnknownType(){
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,4 +45,9 @@ public interface TemporalJavaType<T> extends BasicJavaType<T> {
|
|||
<X> TemporalJavaType<X> resolveTypeForPrecision(
|
||||
TemporalType precision,
|
||||
TypeConfiguration typeConfiguration);
|
||||
|
||||
@Override
|
||||
default boolean isTemporalType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,4 +76,9 @@ public class UnknownBasicJavaType<T> extends AbstractJavaType<T> {
|
|||
public String toString() {
|
||||
return "BasicJavaType(" + getJavaType().getTypeName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnknownType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.hibernate.type.format.FormatMapper;
|
|||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
||||
|
||||
import jakarta.xml.bind.JAXBContext;
|
||||
import jakarta.xml.bind.JAXBElement;
|
||||
|
@ -450,7 +449,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper {
|
|||
.getTypeConfiguration()
|
||||
.getJavaTypeRegistry()
|
||||
.findDescriptor( elementClass );
|
||||
if ( exampleElement == null && ( elementJavaType == null || elementJavaType instanceof UnknownBasicJavaType<?> ) ) {
|
||||
if ( exampleElement == null && ( elementJavaType == null || elementJavaType.isUnknownType() ) ) {
|
||||
try {
|
||||
final Constructor<?> declaredConstructor = elementClass.getDeclaredConstructor();
|
||||
exampleElement = declaredConstructor.newInstance();
|
||||
|
@ -480,7 +479,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper {
|
|||
Object exampleElement,
|
||||
JAXBIntrospector introspector,
|
||||
WrapperOptions wrapperOptions) {
|
||||
if ( exampleElement == null && elementJavaType instanceof UnknownBasicJavaType<?> ) {
|
||||
if ( exampleElement == null && elementJavaType.isUnknownType() ) {
|
||||
try {
|
||||
final Constructor<?> declaredConstructor = elementJavaType.getJavaTypeClass().getDeclaredConstructor();
|
||||
exampleElement = declaredConstructor.newInstance();
|
||||
|
|
|
@ -378,8 +378,7 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Department> criteria = criteriaBuilder.createQuery( Department.class );
|
||||
criteria.where( criteriaBuilder.in( criteria.from( Department.class ).get( "id" ) )
|
||||
.value( subquery ) );
|
||||
criteria.where( criteriaBuilder.in( criteria.from( Department.class ) ).value( subquery ) );
|
||||
|
||||
Query<Department> departmentsQuery = session.createQuery( criteria );
|
||||
List<Department> departments = departmentsQuery.list();
|
||||
|
@ -440,7 +439,7 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
session.enableFilter( "region" ).setParameter( "region", "APAC" );
|
||||
session.enableFilter( "effectiveDate" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
|
||||
|
||||
Subquery<Product> productSubquery = detachedCriteriaBuilder.createQuery().subquery( Product.class );
|
||||
Subquery<Long> productSubquery = detachedCriteriaBuilder.createQuery().subquery( Long.class );
|
||||
Root<Product> productRoot = productSubquery.from( Product.class );
|
||||
productSubquery.select( productRoot.get( "id" ) );
|
||||
productSubquery.where( detachedCriteriaBuilder.equal(
|
||||
|
@ -549,7 +548,7 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
session.enableFilter( "region" ).setParameter( "region", "APAC" );
|
||||
|
||||
List orders = session.createQuery(
|
||||
"select o from Order as o where exists (select li.id from LineItem li, Product as p where p.id = li.product and li.quantity >= ?1 and p.name = ?2) and o.buyer = ?3" )
|
||||
"select o from Order as o where exists (select li.id from LineItem li, Product as p where p.id = li.product.id and li.quantity >= ?1 and p.name = ?2) and o.buyer = ?3" )
|
||||
.setParameter( 1, 1L ).setParameter( 2, "Acme Hair Gel" ).setParameter( 3, "gavin" ).list();
|
||||
|
||||
assertEquals( "Incorrect orders count", 1, orders.size() );
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
package org.hibernate.orm.test.jpa.criteria;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.type.descriptor.java.CoercionException;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
|
||||
@Jpa(
|
||||
annotatedClasses = {
|
||||
QueryPredicateAndParameterComparableTest.Participation.class,
|
||||
QueryPredicateAndParameterComparableTest.Submission.class
|
||||
}
|
||||
)
|
||||
@TestForIssue(jiraKey = "HHH-15802")
|
||||
public class QueryPredicateAndParameterComparableTest {
|
||||
|
||||
@Test
|
||||
public void testWrongInPredicateType(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Participation> criteria = builder.createQuery( Participation.class );
|
||||
Root<Participation> root = criteria.from( Participation.class );
|
||||
criteria.select( root );
|
||||
|
||||
Subquery<Participation> subQuery = criteria.subquery( Participation.class );
|
||||
Root<Submission> rootSubQuery = subQuery.from( Submission.class );
|
||||
subQuery.select( rootSubQuery.join( "submitters" ) );
|
||||
|
||||
criteria.where( root.get( "id" ).in( subQuery ) );
|
||||
entityManager.createQuery( criteria ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectInPredicateType(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Participation> criteria = builder.createQuery( Participation.class );
|
||||
Root<Participation> root = criteria.from( Participation.class );
|
||||
criteria.select( root );
|
||||
|
||||
Subquery<Participation> subQuery = criteria.subquery( Participation.class );
|
||||
Root<Participation> rootSubQuery = subQuery.from( Participation.class );
|
||||
subQuery.select( rootSubQuery );
|
||||
|
||||
criteria.where( root.in( subQuery ) );
|
||||
entityManager.createQuery( criteria ).getResultList();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongInPredicateType2(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Participation> criteria = builder.createQuery( Participation.class );
|
||||
Root<Participation> root = criteria.from( Participation.class );
|
||||
criteria.select( root );
|
||||
|
||||
Subquery<Participation> subQuery = criteria.subquery( Participation.class );
|
||||
Root<Submission> rootSubQuery = subQuery.from( Submission.class );
|
||||
subQuery.select( rootSubQuery.get( "participation" ) );
|
||||
|
||||
criteria.where( root.get( "id" ).in( subQuery ) );
|
||||
entityManager.createQuery( criteria ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongTypeEqualPredicate(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
CoercionException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Participation> criteria = builder.createQuery( Participation.class );
|
||||
Root<Participation> root = criteria.from( Participation.class );
|
||||
criteria.select( root );
|
||||
|
||||
Subquery<Participation> subQuery = criteria.subquery( Participation.class );
|
||||
Root<Submission> rootSubQuery = subQuery.from( Submission.class );
|
||||
subQuery.select( rootSubQuery.get( "participation" ) );
|
||||
|
||||
criteria.where( builder.equal( root.get( "id" ), new Participation() ) );
|
||||
entityManager.createQuery( criteria ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongTypeEqualPredicate2(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Participation> criteria = builder.createQuery( Participation.class );
|
||||
Root<Participation> root = criteria.from( Participation.class );
|
||||
criteria.select( root );
|
||||
|
||||
Subquery<Participation> subQuery = criteria.subquery( Participation.class );
|
||||
Root<Submission> rootSubQuery = subQuery.from( Submission.class );
|
||||
subQuery.select( rootSubQuery.get( "participation" ) );
|
||||
|
||||
criteria.where( builder.equal( root, 1 ) );
|
||||
entityManager.createQuery( criteria ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
entityManager.createQuery( "select p from participations p where p = 1" ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongTypeParameter(EntityManagerFactoryScope scope) {
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class, () -> scope.inTransaction(
|
||||
entityManager -> {
|
||||
entityManager.createQuery( "select p from participations p where p = :id" ).setParameter( "id", 1 ).getResultList();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "participations")
|
||||
public static class Participation {
|
||||
|
||||
private int id;
|
||||
|
||||
private String description;
|
||||
|
||||
private Set<Submission> submissions;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(name = "submissions_participations", joinColumns = @JoinColumn(name = "submitters_id"), inverseJoinColumns = @JoinColumn(name = "submissions_submissionid"))
|
||||
public Set<Submission> getSubmissions() {
|
||||
return submissions;
|
||||
}
|
||||
|
||||
public void setSubmissions(Set<Submission> submissions) {
|
||||
this.submissions = submissions;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "submissions")
|
||||
public class Submission {
|
||||
|
||||
private int submissionid;
|
||||
|
||||
private String description;
|
||||
|
||||
private Set<Participation> submitters = new HashSet<>();
|
||||
|
||||
private Participation participation;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "submissions_participations", inverseJoinColumns = @JoinColumn(name = "submitters_id"), joinColumns = @JoinColumn(name = "submissions_submissionid"))
|
||||
public Set<Participation> getSubmitters() {
|
||||
return submitters;
|
||||
}
|
||||
|
||||
public void setSubmitters(Set<Participation> submitters) {
|
||||
this.submitters = submitters;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
public int getSubmissionid() {
|
||||
return submissionid;
|
||||
}
|
||||
|
||||
public void setSubmissionid(int submissionid) {
|
||||
this.submissionid = submissionid;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
public Participation getParticipation() {
|
||||
return participation;
|
||||
}
|
||||
|
||||
public void setParticipation(Participation participation) {
|
||||
this.participation = participation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,6 @@ public class IdClassQueryRefTests {
|
|||
public void testHqlVirtualIdReferences(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.createQuery( "from Order o where o.orderNumber = 123" ).list();
|
||||
session.createQuery( "from Order o where o.customer = 1" ).list();
|
||||
session.createQuery( "from Order o where o.customer.id = 1" ).list();
|
||||
} );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue