Skip to content

Commit acb7ef5

Browse files
committed
HHH-19364 make Specification subtypes into TypedQueryReferences
1 parent bb0be44 commit acb7ef5

File tree

6 files changed

+84
-11
lines changed

6 files changed

+84
-11
lines changed

hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import jakarta.persistence.criteria.CriteriaDelete;
1111
import jakarta.persistence.criteria.CriteriaQuery;
1212
import jakarta.persistence.criteria.CriteriaUpdate;
13+
import jakarta.persistence.criteria.CommonAbstractCriteria;
14+
1315
import org.checkerframework.checker.nullness.qual.Nullable;
1416
import org.hibernate.CacheMode;
1517
import org.hibernate.EntityNameResolver;
@@ -71,6 +73,8 @@
7173
import org.hibernate.query.hql.spi.SqmQueryImplementor;
7274
import org.hibernate.query.named.NamedObjectRepository;
7375
import org.hibernate.query.named.NamedResultSetMappingMemento;
76+
import org.hibernate.query.programmatic.MutationSpecification;
77+
import org.hibernate.query.programmatic.SelectionSpecification;
7478
import org.hibernate.query.spi.HqlInterpretation;
7579
import org.hibernate.query.spi.QueryImplementor;
7680
import org.hibernate.query.sql.internal.NativeQueryImpl;
@@ -901,15 +905,25 @@ public <T> QueryImplementor<T> createQuery(String queryString, Class<T> expected
901905
@Override
902906
public <R> QueryImplementor<R> createQuery(TypedQueryReference<R> typedQueryReference) {
903907
checksBeforeQueryCreation();
904-
@SuppressWarnings("unchecked")
905-
// this cast is fine because of all our impls of TypedQueryReference return Class<R>
906-
final Class<R> resultType = (Class<R>) typedQueryReference.getResultType();
907-
final QueryImplementor<R> query =
908-
buildNamedQuery( typedQueryReference.getName(),
909-
memento -> createSqmQueryImplementor( resultType, memento ),
910-
memento -> createNativeQueryImplementor( resultType, memento ) );
911-
typedQueryReference.getHints().forEach( query::setHint );
912-
return query;
908+
if ( typedQueryReference instanceof SelectionSpecification<R> specification ) {
909+
final CriteriaQuery<R> query = specification.buildCriteria( getCriteriaBuilder() );
910+
return new QuerySqmImpl<>( (SqmStatement<R>) query, specification.getResultType(), this );
911+
}
912+
else if ( typedQueryReference instanceof MutationSpecification<?> specification ) {
913+
final CommonAbstractCriteria query = specification.buildCriteria( getCriteriaBuilder() );
914+
return new QuerySqmImpl<>( (SqmStatement<R>) query, (Class<R>) specification.getResultType(), this );
915+
}
916+
else {
917+
@SuppressWarnings("unchecked")
918+
// this cast is fine because of all our impls of TypedQueryReference return Class<R>
919+
final Class<R> resultType = (Class<R>) typedQueryReference.getResultType();
920+
final QueryImplementor<R> query =
921+
buildNamedQuery( typedQueryReference.getName(),
922+
memento -> createSqmQueryImplementor( resultType, memento ),
923+
memento -> createNativeQueryImplementor( resultType, memento ) );
924+
typedQueryReference.getHints().forEach( query::setHint );
925+
return query;
926+
}
913927
}
914928

915929
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

hibernate-core/src/main/java/org/hibernate/query/specification/MutationSpecification.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
*/
55
package org.hibernate.query.specification;
66

7+
import jakarta.persistence.TypedQueryReference;
78
import jakarta.persistence.criteria.CommonAbstractCriteria;
89
import jakarta.persistence.criteria.CriteriaUpdate;
910
import jakarta.persistence.criteria.CriteriaDelete;
1011
import jakarta.persistence.criteria.CriteriaBuilder;
1112
import jakarta.persistence.criteria.Root;
13+
1214
import org.hibernate.Incubating;
1315
import org.hibernate.Session;
1416
import org.hibernate.StatelessSession;
@@ -37,7 +39,7 @@
3739
* @since 7.0
3840
*/
3941
@Incubating
40-
public interface MutationSpecification<T> extends QuerySpecification<T> {
42+
public interface MutationSpecification<T> extends QuerySpecification<T>, TypedQueryReference<Void> {
4143

4244
/**
4345
* Covariant override.
@@ -79,6 +81,9 @@ interface Augmentation<T> {
7981
@Override
8082
MutationSpecification<T> validate(CriteriaBuilder builder);
8183

84+
@Override
85+
Class<Void> getResultType();
86+
8287
/**
8388
* Returns a specification reference which can be used to programmatically,
8489
* iteratively build a {@linkplain MutationQuery} based on a base HQL statement,

hibernate-core/src/main/java/org/hibernate/query/specification/SelectionSpecification.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.hibernate.query.specification;
66

77
import jakarta.persistence.EntityManager;
8+
import jakarta.persistence.TypedQueryReference;
89
import jakarta.persistence.criteria.CriteriaQuery;
910
import jakarta.persistence.criteria.CriteriaBuilder;
1011
import jakarta.persistence.criteria.Root;
@@ -59,7 +60,7 @@
5960
* @since 7.0
6061
*/
6162
@Incubating
62-
public interface SelectionSpecification<T> extends QuerySpecification<T> {
63+
public interface SelectionSpecification<T> extends QuerySpecification<T>, TypedQueryReference<T> {
6364
/**
6465
* Adds an ordering to the selection specification.
6566
* Appended to any previous ordering.
@@ -185,6 +186,9 @@ interface Augmentation<T> {
185186
@Override
186187
SelectionSpecification<T> validate(CriteriaBuilder builder);
187188

189+
@Override
190+
Class<T> getResultType();
191+
188192
/**
189193
* Returns a specification reference which can be used to programmatically,
190194
* iteratively build a {@linkplain SelectionQuery} for the given entity type,

hibernate-core/src/main/java/org/hibernate/query/specification/internal/MutationSpecificationImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
3434

3535
import java.util.ArrayList;
36+
import java.util.Collections;
3637
import java.util.List;
3738
import java.util.Locale;
39+
import java.util.Map;
3840
import java.util.function.BiConsumer;
3941

4042
import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext;
@@ -69,6 +71,21 @@ public MutationSpecificationImpl(CriteriaDelete<T> criteriaQuery) {
6971
this.hql = null;
7072
}
7173

74+
@Override
75+
public String getName() {
76+
return null;
77+
}
78+
79+
@Override
80+
public Class<Void> getResultType() {
81+
return Void.class;
82+
}
83+
84+
@Override
85+
public Map<String,Object> getHints() {
86+
return Collections.emptyMap();
87+
}
88+
7289
@Override
7390
public MutationSpecification<T> restrict(Restriction<? super T> restriction) {
7491
specifications.add( (sqmStatement, mutationTargetRoot) -> {

hibernate-core/src/main/java/org/hibernate/query/specification/internal/SelectionSpecificationImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.hibernate.type.descriptor.java.JavaType;
3737

3838
import java.util.ArrayList;
39+
import java.util.Collections;
3940
import java.util.List;
4041
import java.util.Locale;
4142
import java.util.Map;
@@ -74,6 +75,21 @@ public SelectionSpecificationImpl(CriteriaQuery<T> criteriaQuery) {
7475
this.criteriaQuery = criteriaQuery;
7576
}
7677

78+
@Override
79+
public String getName() {
80+
return null;
81+
}
82+
83+
@Override
84+
public Class<T> getResultType() {
85+
return resultType;
86+
}
87+
88+
@Override
89+
public Map<String,Object> getHints() {
90+
return Collections.emptyMap();
91+
}
92+
7793
@Override
7894
public SelectionSpecification<T> restrict(Restriction<? super T> restriction) {
7995
specifications.add( (sqmStatement, root) -> {

hibernate-core/src/test/java/org/hibernate/orm/test/query/dynamic/SimpleQuerySpecificationTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,21 @@ void testBuildCriteriaQuery(SessionFactoryScope factoryScope) {
296296
.validate( factory.getCriteriaBuilder() )
297297
.buildCriteria( factory.getCriteriaBuilder() );
298298
}
299+
300+
@Test
301+
void testUseAsTypedQueryRef(SessionFactoryScope factoryScope) {
302+
final SQLStatementInspector sqlCollector = factoryScope.getCollectingStatementInspector();
303+
304+
factoryScope.inTransaction( (session) -> {
305+
sqlCollector.clear();
306+
var spec = SelectionSpecification.create( BasicEntity.class )
307+
.restrict( Restriction.restrict( BasicEntity_.position, Range.closed( 1, 5 ) ) )
308+
.sort( Order.asc( BasicEntity_.position ) );
309+
session.createQuery(spec).getResultList();
310+
} );
311+
312+
assertThat( sqlCollector.getSqlQueries() ).hasSize( 1 );
313+
assertThat( sqlCollector.getSqlQueries().get( 0 ) ).contains( " order by be1_0.position" );
314+
}
315+
299316
}

0 commit comments

Comments
 (0)