Skip to content

Commit 6b7e8b7

Browse files
committed
some code reorg related to dynamic instantiation
1 parent 80fb595 commit 6b7e8b7

File tree

6 files changed

+117
-111
lines changed

6 files changed

+117
-111
lines changed

hibernate-core/src/main/java/org/hibernate/query/criteria/CriteriaDefinition.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,12 @@ public JpaCriteriaQuery<R> select(Selection<? extends R> selection) {
232232
return query.select(selection);
233233
}
234234

235-
@Override
235+
@Override @Deprecated
236236
public JpaCriteriaQuery<R> multiselect(Selection<?>... selections) {
237237
return query.multiselect(selections);
238238
}
239239

240-
@Override
240+
@Override @Deprecated
241241
public JpaCriteriaQuery<R> multiselect(List<Selection<?>> list) {
242242
return query.multiselect(list);
243243
}

hibernate-core/src/main/java/org/hibernate/query/criteria/JpaCriteriaQuery.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ public interface JpaCriteriaQuery<T> extends CriteriaQuery<T>, JpaQueryableCrite
114114
@Override
115115
JpaCriteriaQuery<T> select(Selection<? extends T> selection);
116116

117-
@Override
117+
@Override @Deprecated
118118
JpaCriteriaQuery<T> multiselect(Selection<?>... selections);
119119

120-
@Override
120+
@Override @Deprecated
121121
JpaCriteriaQuery<T> multiselect(List<Selection<?>> selectionList);
122122

123123
@Override

hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@
241241
import static org.hibernate.query.common.TemporalUnit.WEEK_OF_MONTH;
242242
import static org.hibernate.query.common.TemporalUnit.WEEK_OF_YEAR;
243243
import static org.hibernate.query.sqm.internal.SqmUtil.resolveExpressibleJavaTypeClass;
244+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.forClassInstantiation;
245+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.forListInstantiation;
246+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.forMapInstantiation;
244247
import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME;
245248
import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
246249

@@ -1428,8 +1431,8 @@ private SqmSelectableNode<?> visitSelectableNode(HqlParser.SelectionContext ctx)
14281431
// - this is not strictly JPA compliant
14291432
if ( creationOptions.useStrictJpaCompliance() ) {
14301433
SqmTreeCreationLogger.LOGGER.debugf(
1431-
"Raw selection of plural attribute not supported by JPA: %s. Use `value(%s)` or `key(%s)` to indicate what part of the collection to select",
1432-
sqmPath.getAlias(),
1434+
"Raw selection of plural attribute not supported by JPA."
1435+
+ " Use 'value(%s)' or 'key(%s)' to indicate what part of the collection to select",
14331436
sqmPath.getAlias(),
14341437
sqmPath.getAlias()
14351438
);
@@ -1448,35 +1451,7 @@ private SqmSelectableNode<?> visitSelectableNode(HqlParser.SelectionContext ctx)
14481451

14491452
@Override
14501453
public SqmDynamicInstantiation<?> visitInstantiation(HqlParser.InstantiationContext ctx) {
1451-
final SqmDynamicInstantiation<?> dynamicInstantiation;
1452-
final ParseTree instantiationTarget = ctx.instantiationTarget().getChild( 0 );
1453-
if ( instantiationTarget instanceof HqlParser.SimplePathContext ) {
1454-
String className = instantiationTarget.getText();
1455-
if ( expectedResultTypeName != null && expectedResultTypeShortName.equals( className ) ) {
1456-
className = expectedResultTypeName;
1457-
}
1458-
try {
1459-
dynamicInstantiation = SqmDynamicInstantiation.forClassInstantiation(
1460-
resolveInstantiationTargetJtd( className ),
1461-
creationContext.getNodeBuilder()
1462-
);
1463-
}
1464-
catch (ClassLoadingException e) {
1465-
throw new SemanticException( "Could not resolve class '" + className + "' named for instantiation",
1466-
query );
1467-
}
1468-
}
1469-
else {
1470-
final TerminalNode terminalNode = (TerminalNode) instantiationTarget;
1471-
dynamicInstantiation = switch ( terminalNode.getSymbol().getType() ) {
1472-
case HqlParser.MAP -> SqmDynamicInstantiation.forMapInstantiation( mapJavaType,
1473-
creationContext.getNodeBuilder() );
1474-
case HqlParser.LIST -> SqmDynamicInstantiation.forListInstantiation( listJavaType,
1475-
creationContext.getNodeBuilder() );
1476-
default -> throw new UnsupportedOperationException( "Unsupported instantiation target: " + terminalNode );
1477-
};
1478-
}
1479-
1454+
final SqmDynamicInstantiation<?> dynamicInstantiation = visitInstantiationTarget( ctx.instantiationTarget() );
14801455
for ( HqlParser.InstantiationArgumentContext arg : ctx.instantiationArguments().instantiationArgument() ) {
14811456
dynamicInstantiation.addArgument( visitInstantiationArgument( arg ) );
14821457
}
@@ -1494,7 +1469,37 @@ public SqmDynamicInstantiation<?> visitInstantiation(HqlParser.InstantiationCont
14941469
return dynamicInstantiation;
14951470
}
14961471

1497-
private JavaType<?> resolveInstantiationTargetJtd(String className) {
1472+
@Override
1473+
public SqmDynamicInstantiation<?> visitInstantiationTarget(HqlParser.InstantiationTargetContext ctx) {
1474+
if ( ctx.MAP() != null ) {
1475+
return forMapInstantiation( mapJavaType, creationContext.getNodeBuilder() );
1476+
}
1477+
else if ( ctx.LIST() != null ) {
1478+
return forListInstantiation( listJavaType, creationContext.getNodeBuilder() );
1479+
}
1480+
else {
1481+
final HqlParser.SimplePathContext simplePath = ctx.simplePath();
1482+
if ( simplePath == null ) {
1483+
throw new SyntaxException( "Missing instantiation target type" );
1484+
}
1485+
final String className = instantiationClassName( simplePath );
1486+
try {
1487+
return forClassInstantiation( resolveInstantiationTargetType( className ), creationContext.getNodeBuilder() );
1488+
}
1489+
catch (ClassLoadingException e) {
1490+
throw new SemanticException( "Could not resolve class '" + className + "' named for instantiation", query );
1491+
}
1492+
}
1493+
}
1494+
1495+
private String instantiationClassName(HqlParser.SimplePathContext ctx) {
1496+
final String name = ctx.getText();
1497+
return expectedResultTypeName != null && expectedResultTypeShortName.equals( name )
1498+
? expectedResultTypeName
1499+
: name;
1500+
}
1501+
1502+
private JavaType<?> resolveInstantiationTargetType(String className) {
14981503
final String qualifiedName = creationContext.getJpaMetamodel().qualifyImportableName( className );
14991504
final Class<?> targetJavaType = creationContext.classForName( qualifiedName );
15001505
return creationContext.getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( targetJavaType );
@@ -1504,20 +1509,13 @@ private JavaType<?> resolveInstantiationTargetJtd(String className) {
15041509
public SqmDynamicInstantiationArgument<?> visitInstantiationArgument(HqlParser.InstantiationArgumentContext ctx) {
15051510
final HqlParser.VariableContext variable = ctx.variable();
15061511
final String alias = variable == null ? null : extractAlias( variable );
1507-
15081512
final SqmSelectableNode<?> argExpression =
15091513
(SqmSelectableNode<?>) ctx.instantiationArgumentExpression().accept( this );
1510-
1511-
final SqmDynamicInstantiationArgument<?> argument = new SqmDynamicInstantiationArgument<>(
1512-
argExpression,
1513-
alias,
1514-
creationContext.getNodeBuilder()
1515-
);
1516-
1514+
final SqmDynamicInstantiationArgument<?> argument =
1515+
new SqmDynamicInstantiationArgument<>( argExpression, alias, creationContext.getNodeBuilder() );
15171516
if ( !(argExpression instanceof SqmDynamicInstantiation) ) {
15181517
processingStateStack.getCurrent().getPathRegistry().register( argument );
15191518
}
1520-
15211519
return argument;
15221520
}
15231521

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
128128
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
129129
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
130-
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
131130
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
132131
import org.hibernate.query.sqm.tree.select.SqmOrderByClause;
133132
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
@@ -169,6 +168,9 @@
169168
import static org.hibernate.internal.util.collections.CollectionHelper.determineProperSizing;
170169
import static org.hibernate.query.internal.QueryHelper.highestPrecedenceType;
171170
import static org.hibernate.query.sqm.TrimSpec.fromCriteriaTrimSpec;
171+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.classInstantiation;
172+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.listInstantiation;
173+
import static org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation.mapInstantiation;
172174

173175
/**
174176
* Acts as a JPA {@link jakarta.persistence.criteria.CriteriaBuilder} by
@@ -374,7 +376,7 @@ public <T> SqmInsertSelectStatement<T> createCriteriaInsertSelect(Class<T> targe
374376

375377
@Override
376378
public SqmValues values(Expression<?>... expressions) {
377-
return values( Arrays.asList( expressions ) );
379+
return values( asList( expressions ) );
378380
}
379381

380382
@Override
@@ -873,15 +875,14 @@ public JpaSearchOrder desc(JpaCteCriteriaAttribute x, boolean nullsFirst) {
873875

874876
@Override
875877
public JpaCompoundSelection<Tuple> tuple(Selection<?>... selections) {
876-
return tuple( Arrays.asList( selections ) );
878+
return tuple( asList( selections ) );
877879
}
878880

879881
@Override
880882
public JpaCompoundSelection<Tuple> tuple(List<Selection<?>> selections) {
881883
checkMultiselect( selections );
882-
//noinspection unchecked,rawtypes
883884
return new SqmJpaCompoundSelection<>(
884-
(List) selections,
885+
selections.stream().map( selection -> (SqmSelectableNode<?>) selection ).toList(),
885886
getTypeConfiguration().getJavaTypeRegistry().getDescriptor( Tuple.class ),
886887
this
887888
);
@@ -892,6 +893,11 @@ public <R> SqmTuple<R> tuple(Class<R> tupleType, SqmExpression<?>... expressions
892893
return tuple( tupleType, asList( expressions ) );
893894
}
894895

896+
@Override
897+
public <R> SqmTuple<R> tuple(SqmExpressible<R> tupleType, SqmExpression<?>... expressions) {
898+
return tuple( tupleType, asList( expressions ) );
899+
}
900+
895901
@Override @SuppressWarnings("unchecked")
896902
public <R> SqmTuple<R> tuple(Class<R> tupleType, List<? extends SqmExpression<?>> expressions) {
897903
final SqmExpressible<R> expressibleType =
@@ -901,11 +907,6 @@ public <R> SqmTuple<R> tuple(Class<R> tupleType, List<? extends SqmExpression<?>
901907
return tuple( expressibleType, expressions );
902908
}
903909

904-
@Override
905-
public <R> SqmTuple<R> tuple(SqmExpressible<R> tupleType, SqmExpression<?>... expressions) {
906-
return tuple( tupleType, asList( expressions ) );
907-
}
908-
909910
@Override
910911
public <R> SqmTuple<R> tuple(SqmExpressible<R> tupleType, List<? extends SqmExpression<?>> sqmExpressions) {
911912
if ( tupleType == null ) {
@@ -957,63 +958,51 @@ public <Y> JpaCompoundSelection<Y> construct(Class<Y> resultClass, List<? extend
957958
arguments.stream().map( arg -> (SqmSelectableNode<?>) arg ).toList() );
958959
}
959960

961+
@SuppressWarnings("unchecked")
960962
private <Y> JpaCompoundSelection<Y> constructInternal(Class<Y> resultClass, List<? extends SqmSelectableNode<?>> arguments) {
961963
checkMultiselect( arguments );
962-
final SqmDynamicInstantiation<Y> instantiation = createInstantiation( resultClass );
963-
for ( SqmSelectableNode<?> argument : arguments ) {
964-
final SqmDynamicInstantiationArgument<?> arg =
965-
new SqmDynamicInstantiationArgument<>( argument, argument.getAlias(), this );
966-
instantiation.addArgument( arg );
967-
}
968-
return instantiation;
969-
}
970-
971-
@SuppressWarnings("unchecked")
972-
private <Y> SqmDynamicInstantiation<Y> createInstantiation(Class<Y> resultClass) {
973964
if ( List.class.equals( resultClass ) ) {
974-
return (SqmDynamicInstantiation<Y>) SqmDynamicInstantiation.forListInstantiation( this );
965+
return (SqmDynamicInstantiation<Y>) listInstantiation( arguments, this );
975966
}
976967
else if ( Map.class.equals( resultClass ) ) {
977-
return (SqmDynamicInstantiation<Y>) SqmDynamicInstantiation.forMapInstantiation( this );
968+
return (SqmDynamicInstantiation<Y>) mapInstantiation( arguments, this );
978969
}
979970
else {
980-
return SqmDynamicInstantiation.forClassInstantiation( resultClass, this );
971+
return classInstantiation( resultClass, arguments, this );
981972
}
982973
}
983974

984975
/**
985-
* Package-protected method to centralize checking of criteria query multi-selects as defined by the
986-
* {@link CriteriaQuery#multiselect(List)} method.
976+
* Check the arguments of {@link jakarta.persistence.criteria.CriteriaBuilder#array},
977+
* {@link jakarta.persistence.criteria.CriteriaBuilder#construct}, or
978+
* {@link jakarta.persistence.criteria.CriteriaBuilder#tuple}.
987979
*
988980
* @param selections The selection varargs to check
989981
*
990-
* @throws IllegalArgumentException If the selection items are not valid per {@link CriteriaQuery#multiselect}
991-
* documentation.
992-
* <i>&quot;An argument to the multiselect method must not be a tuple-
993-
* or array-valued compound selection item.&quot;</i>
982+
* @throws IllegalArgumentException If the selection items are not valid per
983+
* according to {@linkplain CriteriaQuery#multiselect this documentation}.
984+
* <i>&quot;An argument to the multiselect method must not be a tuple-
985+
* or array-valued compound selection item.&quot;</i>
994986
*/
995-
void checkMultiselect(List<? extends Selection<?>> selections) {
987+
private void checkMultiselect(List<? extends Selection<?>> selections) {
996988
final HashSet<String> aliases = new HashSet<>( determineProperSizing( selections.size() ) );
997-
998-
for ( Selection<?> it : selections ) {
999-
final JpaSelection<?> selection = (JpaSelection<?>) it;
989+
for ( Selection<?> selection : selections ) {
1000990
if ( selection.isCompoundSelection() ) {
1001-
if ( selection.getJavaType().isArray() ) {
991+
final Class<?> javaType = selection.getJavaType();
992+
if ( javaType.isArray() ) {
1002993
throw new IllegalArgumentException(
1003-
"Selection items in a multi-select cannot contain compound array-valued elements"
994+
"Selection item in a multi-select cannot contain compound array-valued elements"
1004995
);
1005996
}
1006-
if ( Tuple.class.isAssignableFrom( selection.getJavaType() ) ) {
997+
if ( Tuple.class.isAssignableFrom( javaType ) ) {
1007998
throw new IllegalArgumentException(
1008-
"Selection items in a multi-select cannot contain compound tuple-valued elements"
999+
"Selection item in a multi-select cannot contain compound tuple-valued elements"
10091000
);
10101001
}
10111002
}
1012-
if ( StringHelper.isNotEmpty( selection.getAlias() ) ) {
1013-
boolean added = aliases.add( selection.getAlias() );
1014-
if ( ! added ) {
1015-
throw new IllegalArgumentException( "Multi-select expressions defined duplicate alias : " + selection.getAlias() );
1016-
}
1003+
final String alias = selection.getAlias();
1004+
if ( StringHelper.isNotEmpty( alias ) && !aliases.add( alias ) ) {
1005+
throw new IllegalArgumentException( "Multi-select expressions have duplicate alias '" + alias + "'" );
10171006
}
10181007
}
10191008
}
@@ -1161,7 +1150,7 @@ public JpaExpression<Double> ln(Expression<? extends Number> x) {
11611150
@Override
11621151
public JpaExpression<Double> power(Expression<? extends Number> x, Expression<? extends Number> y) {
11631152
return getFunctionDescriptor( "power" ).generateSqmExpression(
1164-
Arrays.asList( (SqmExpression<?>) x, (SqmExpression<?>) y),
1153+
asList( (SqmExpression<?>) x, (SqmExpression<?>) y),
11651154
null,
11661155
queryEngine
11671156
);
@@ -1170,7 +1159,7 @@ public JpaExpression<Double> power(Expression<? extends Number> x, Expression<?
11701159
@Override
11711160
public JpaExpression<Double> power(Expression<? extends Number> x, Number y) {
11721161
return getFunctionDescriptor( "power" ).generateSqmExpression(
1173-
Arrays.asList( (SqmExpression<?>) x, value( y ) ),
1162+
asList( (SqmExpression<?>) x, value( y ) ),
11741163
null,
11751164
queryEngine
11761165
);
@@ -1179,7 +1168,7 @@ public JpaExpression<Double> power(Expression<? extends Number> x, Number y) {
11791168
@Override
11801169
public <T extends Number> JpaExpression<T> round(Expression<T> x, Integer n) {
11811170
return getFunctionDescriptor( "round" ).generateSqmExpression(
1182-
Arrays.asList( (SqmExpression<?>) x, value( n ) ),
1171+
asList( (SqmExpression<?>) x, value( n ) ),
11831172
null,
11841173
queryEngine
11851174
);
@@ -1188,7 +1177,7 @@ public <T extends Number> JpaExpression<T> round(Expression<T> x, Integer n) {
11881177
@Override
11891178
public <T extends Number> JpaExpression<T> truncate(Expression<T> x, Integer n) {
11901179
return getFunctionDescriptor( "truncate" ).generateSqmExpression(
1191-
Arrays.asList( (SqmExpression<?>) x, value( n ) ),
1180+
asList( (SqmExpression<?>) x, value( n ) ),
11921181
null,
11931182
queryEngine
11941183
);
@@ -5532,7 +5521,7 @@ private SqmExpression<String> jsonArrayAgg(
55325521
return getFunctionDescriptor( "json_arrayagg" ).generateOrderedSetAggregateSqmExpression(
55335522
nullBehavior == null
55345523
? Collections.singletonList( value )
5535-
: Arrays.asList( value, SqmJsonNullBehavior.NULL ),
5524+
: asList( value, SqmJsonNullBehavior.NULL ),
55365525
filterPredicate,
55375526
orderByClause,
55385527
null,
@@ -5712,7 +5701,7 @@ public <T> SqmExpression<T> named(Expression<T> expression, String name) {
57125701

57135702
@Override
57145703
public SqmExpression<String> xmlforest(Expression<?>... elements) {
5715-
return xmlforest( Arrays.asList( elements ) );
5704+
return xmlforest( asList( elements ) );
57165705
}
57175706

57185707
@Override
@@ -5741,7 +5730,7 @@ public SqmExpression<String> xmlforest(List<? extends Expression<?>> elements) {
57415730

57425731
@Override
57435732
public SqmExpression<String> xmlconcat(Expression<?>... elements) {
5744-
return xmlconcat( Arrays.asList( elements ) );
5733+
return xmlconcat( asList( elements ) );
57455734
}
57465735

57475736
@Override

0 commit comments

Comments
 (0)