Skip to content

Commit 03fecd3

Browse files
committed
[hibernate#2214] Support TypedQueryReferencea and QuerySpecification
1 parent 8a5a650 commit 03fecd3

File tree

9 files changed

+172
-9
lines changed

9 files changed

+172
-9
lines changed

hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java

+33
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import jakarta.persistence.FlushModeType;
3838
import jakarta.persistence.LockModeType;
3939
import jakarta.persistence.Parameter;
40+
import jakarta.persistence.TypedQueryReference;
4041
import jakarta.persistence.criteria.CriteriaBuilder;
4142
import jakarta.persistence.criteria.CriteriaDelete;
4243
import jakarta.persistence.criteria.CriteriaQuery;
@@ -961,6 +962,22 @@ default Uni<Void> lock(Object entity, LockModeType lockModeType) {
961962
*/
962963
MutationQuery createMutationQuery(JpaCriteriaInsert<?> insert);
963964

965+
/**
966+
* Create a typed {@link org.hibernate.query.Query} instance for the given typed query reference.
967+
*
968+
* @param typedQueryReference the type query reference
969+
*
970+
* @return The {@link org.hibernate.query.Query} instance for execution
971+
*
972+
* @throws IllegalArgumentException if a query has not been
973+
* defined with the name of the typed query reference or if
974+
* the query result is found to not be assignable to
975+
* result class of the typed query reference
976+
*
977+
* @see org.hibernate.query.QueryProducer#createQuery(TypedQueryReference)
978+
*/
979+
<R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference);
980+
964981
/**
965982
* Create an instance of {@link Query} for the given HQL/JPQL query
966983
* string or HQL/JPQL update or delete statement. In the case of an
@@ -1616,6 +1633,22 @@ default <T> Uni<T> get(Class<T> entityClass, Object id, LockModeType lockModeTyp
16161633
@Deprecated
16171634
<R> Query<R> createQuery(String queryString);
16181635

1636+
/**
1637+
* Create a typed {@link Query} instance for the given typed query reference.
1638+
*
1639+
* @param typedQueryReference the type query reference
1640+
*
1641+
* @return The {@link Query} instance for execution
1642+
*
1643+
* @throws IllegalArgumentException if a query has not been
1644+
* defined with the name of the typed query reference or if
1645+
* the query result is found to not be assignable to
1646+
* result class of the typed query reference
1647+
*
1648+
* @see org.hibernate.query.QueryProducer#createQuery(TypedQueryReference)
1649+
*/
1650+
<R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference);
1651+
16191652
/**
16201653
* Create an instance of {@link SelectionQuery} for the given HQL/JPQL
16211654
* query string and query result type.

hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import jakarta.persistence.FlushModeType;
1313
import jakarta.persistence.LockModeType;
1414
import jakarta.persistence.PersistenceException;
15+
import jakarta.persistence.TypedQueryReference;
1516
import jakarta.persistence.criteria.CriteriaDelete;
1617
import jakarta.persistence.criteria.CriteriaQuery;
1718
import jakarta.persistence.criteria.CriteriaUpdate;
@@ -34,6 +35,7 @@
3435
import org.hibernate.reactive.mutiny.Mutiny.Query;
3536
import org.hibernate.reactive.mutiny.Mutiny.SelectionQuery;
3637
import org.hibernate.reactive.pool.ReactiveConnection;
38+
import org.hibernate.reactive.query.ReactiveQuery;
3739
import org.hibernate.reactive.session.ReactiveConnectionSupplier;
3840
import org.hibernate.reactive.session.ReactiveQueryProducer;
3941
import org.hibernate.reactive.session.ReactiveSession;
@@ -140,6 +142,12 @@ public MutationQuery createMutationQuery(JpaCriteriaInsert<?> insert) {
140142
return new MutinyMutationQueryImpl<>( delegate.createReactiveMutationQuery( insert ), factory );
141143
}
142144

145+
@Override
146+
public <R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference) {
147+
ReactiveQuery<R> reactiveQuery = delegate.createReactiveQuery( typedQueryReference );
148+
return new MutinyQueryImpl<>( reactiveQuery, factory );
149+
}
150+
143151
@Override @Deprecated
144152
public <R> Query<R> createQuery(String queryString) {
145153
return new MutinyQueryImpl<>( delegate.createReactiveQuery( queryString ), factory );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyStatelessSessionImpl.java

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import io.smallrye.mutiny.Uni;
99
import jakarta.persistence.EntityGraph;
10+
import jakarta.persistence.TypedQueryReference;
1011
import jakarta.persistence.criteria.CriteriaDelete;
1112
import jakarta.persistence.criteria.CriteriaQuery;
1213
import jakarta.persistence.criteria.CriteriaUpdate;
@@ -17,6 +18,7 @@
1718
import org.hibernate.reactive.mutiny.Mutiny.Query;
1819
import org.hibernate.reactive.mutiny.Mutiny.SelectionQuery;
1920
import org.hibernate.reactive.pool.ReactiveConnection;
21+
import org.hibernate.reactive.query.ReactiveQuery;
2022
import org.hibernate.reactive.session.ReactiveStatelessSession;
2123

2224
import java.util.List;
@@ -71,6 +73,12 @@ public <T> Uni<T> get(EntityGraph<T> entityGraph, Object id) {
7173
return uni( () -> delegate.reactiveGet( entityClass, id, null, entityGraph ) );
7274
}
7375

76+
@Override
77+
public <R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference) {
78+
ReactiveQuery<R> reactiveQuery = delegate.createReactiveQuery( typedQueryReference );
79+
return new MutinyQueryImpl<>( reactiveQuery, factory );
80+
}
81+
7482
@Override
7583
public <R> Query<R> createQuery(String queryString) {
7684
return new MutinyQueryImpl<>( delegate.createReactiveQuery( queryString ), factory );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/ReactiveQueryProducer.java

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.hibernate.reactive.session;
77

8+
import jakarta.persistence.TypedQueryReference;
89
import java.util.concurrent.CompletionStage;
910

1011
import org.hibernate.Incubating;
@@ -53,6 +54,8 @@ public interface ReactiveQueryProducer extends ReactiveConnectionSupplier {
5354

5455
<R> ReactiveQuery<R> createReactiveQuery(String queryString);
5556

57+
<R> ReactiveQuery<R> createReactiveQuery(TypedQueryReference<R> typedQueryReference);
58+
5659
<R> ReactiveQuery<R> createReactiveQuery(CriteriaQuery<R> criteriaQuery);
5760

5861
<R> ReactiveQuery<R> createReactiveQuery(String queryString, Class<R> resultType);

hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionImpl.java

+31
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
package org.hibernate.reactive.session.impl;
77

8+
import jakarta.persistence.TypedQueryReference;
9+
import jakarta.persistence.criteria.CommonAbstractCriteria;
810
import java.lang.invoke.MethodHandles;
911
import java.util.List;
1012
import java.util.Map;
@@ -76,6 +78,8 @@
7678
import org.hibernate.query.criteria.JpaCriteriaInsert;
7779
import org.hibernate.query.hql.spi.SqmQueryImplementor;
7880
import org.hibernate.query.named.NamedResultSetMappingMemento;
81+
import org.hibernate.query.specification.internal.MutationSpecificationImpl;
82+
import org.hibernate.query.specification.internal.SelectionSpecificationImpl;
7983
import org.hibernate.query.spi.HqlInterpretation;
8084
import org.hibernate.query.spi.QueryImplementor;
8185
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
@@ -357,6 +361,33 @@ protected <T> ReactiveQueryImplementor<T> createReactiveCriteriaQuery(SqmStateme
357361
return query;
358362
}
359363

364+
@Override
365+
public <R> ReactiveQuery<R> createReactiveQuery(TypedQueryReference<R> typedQueryReference) {
366+
checksBeforeQueryCreation();
367+
if ( typedQueryReference instanceof SelectionSpecificationImpl<R> specification ) {
368+
final CriteriaQuery<R> query = specification.buildCriteria( getCriteriaBuilder() );
369+
return new ReactiveQuerySqmImpl<>( (SqmStatement<R>) query, specification.getResultType(), this );
370+
}
371+
if ( typedQueryReference instanceof MutationSpecificationImpl<?> specification ) {
372+
final CommonAbstractCriteria query = specification.buildCriteria( getCriteriaBuilder() );
373+
// Workaround for ORM, can be remove when this issue is solved: https://hibernate.atlassian.net/browse/HHH-19386
374+
Class<R> type = specification.getResultType() == Void.class
375+
? null
376+
: (Class<R>) specification.getResultType();
377+
return new ReactiveQuerySqmImpl<>( (SqmStatement<R>) query, type, this );
378+
}
379+
@SuppressWarnings("unchecked")
380+
// this cast is fine because of all our impls of TypedQueryReference return Class<R>
381+
final Class<R> resultType = (Class<R>) typedQueryReference.getResultType();
382+
ReactiveQueryImplementor<R> query = (ReactiveQueryImplementor<R>) buildNamedQuery(
383+
typedQueryReference.getName(),
384+
memento -> createSqmQueryImplementor( resultType, memento ),
385+
memento -> createNativeQueryImplementor( resultType, memento )
386+
);
387+
typedQueryReference.getHints().forEach( query::setHint );
388+
return query;
389+
}
390+
360391
@Override
361392
public <R> ReactiveQuery<R> createReactiveQuery(String queryString) {
362393
return createReactiveQuery( queryString, null );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveStatelessSessionImpl.java

+39-9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
import org.hibernate.query.criteria.JpaCriteriaInsert;
4343
import org.hibernate.query.hql.spi.SqmQueryImplementor;
4444
import org.hibernate.query.named.NamedResultSetMappingMemento;
45+
import org.hibernate.query.specification.internal.MutationSpecificationImpl;
46+
import org.hibernate.query.specification.internal.SelectionSpecificationImpl;
4547
import org.hibernate.query.spi.HqlInterpretation;
4648
import org.hibernate.query.spi.QueryImplementor;
4749
import org.hibernate.query.sql.spi.NativeQueryImplementor;
@@ -77,6 +79,8 @@
7779

7880
import jakarta.persistence.EntityGraph;
7981
import jakarta.persistence.Tuple;
82+
import jakarta.persistence.TypedQueryReference;
83+
import jakarta.persistence.criteria.CommonAbstractCriteria;
8084
import jakarta.persistence.criteria.CriteriaDelete;
8185
import jakarta.persistence.criteria.CriteriaQuery;
8286
import jakarta.persistence.criteria.CriteriaUpdate;
@@ -218,15 +222,14 @@ public <T> CompletionStage<List<T>> reactiveGet(Class<T> entityClass, Object...
218222
Object[] sids = new Object[ids.length];
219223
System.arraycopy( ids, 0, sids, 0, ids.length );
220224

221-
final CompletionStage<? extends List<?>> stage =
222-
getEntityPersister( entityClass.getName() )
223-
.reactiveMultiLoad( sids, this, StatelessSessionImpl.MULTI_ID_LOAD_OPTIONS )
224-
.whenComplete( (v, e) -> {
225-
if ( getPersistenceContext().isLoadFinished() ) {
226-
getPersistenceContext().clear();
227-
}
228-
} );
229-
return (CompletionStage<List<T>>) stage;
225+
return getEntityPersister( entityClass.getName() )
226+
.reactiveMultiLoad( sids, this, StatelessSessionImpl.MULTI_ID_LOAD_OPTIONS )
227+
.whenComplete( (v, e) -> {
228+
if ( getPersistenceContext().isLoadFinished() ) {
229+
getPersistenceContext().clear();
230+
}
231+
} )
232+
.thenApply( objects -> (List<T>) objects );
230233
}
231234

232235
@Override
@@ -793,6 +796,33 @@ public <T> RootGraphImplementor<T> getEntityGraph(Class<T> entity, String name)
793796
return (RootGraphImplementor<T>) entityGraph;
794797
}
795798

799+
@Override
800+
public <R> ReactiveQuery<R> createReactiveQuery(TypedQueryReference<R> typedQueryReference) {
801+
checksBeforeQueryCreation();
802+
if ( typedQueryReference instanceof SelectionSpecificationImpl<R> specification ) {
803+
final CriteriaQuery<R> query = specification.buildCriteria( getCriteriaBuilder() );
804+
return new ReactiveQuerySqmImpl<>( (SqmStatement<R>) query, specification.getResultType(), this );
805+
}
806+
if ( typedQueryReference instanceof MutationSpecificationImpl<?> specification ) {
807+
final CommonAbstractCriteria query = specification.buildCriteria( getCriteriaBuilder() );
808+
// Workaround for ORM, can be remove when this issue is solved: https://hibernate.atlassian.net/browse/HHH-19386
809+
Class<R> type = (Class<R>) specification.getResultType() == Void.class
810+
? null
811+
: (Class<R>) specification.getResultType();
812+
return new ReactiveQuerySqmImpl<>( (SqmStatement<R>) query, type, this );
813+
}
814+
@SuppressWarnings("unchecked")
815+
// this cast is fine because of all our impls of TypedQueryReference return Class<R>
816+
final Class<R> resultType = (Class<R>) typedQueryReference.getResultType();
817+
ReactiveQueryImplementor<R> query = (ReactiveQueryImplementor<R>) buildNamedQuery(
818+
typedQueryReference.getName(),
819+
memento -> createSqmQueryImplementor( resultType, memento ),
820+
memento -> createNativeQueryImplementor( resultType, memento )
821+
);
822+
typedQueryReference.getHints().forEach( query::setHint );
823+
return query;
824+
}
825+
796826
@Override
797827
public <R> ReactiveSqmQueryImplementor<R> createReactiveQuery(String queryString) {
798828
return createReactiveQuery( queryString, null );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java

+34
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.hibernate.reactive.stage;
77

8+
import jakarta.persistence.TypedQueryReference;
89
import java.lang.invoke.MethodHandles;
910
import java.util.List;
1011
import java.util.concurrent.CompletionStage;
@@ -25,6 +26,7 @@
2526
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
2627
import org.hibernate.proxy.HibernateProxy;
2728
import org.hibernate.query.Page;
29+
import org.hibernate.query.Query;
2830
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
2931
import org.hibernate.query.criteria.JpaCriteriaInsert;
3032
import org.hibernate.reactive.common.AffectedEntities;
@@ -985,6 +987,22 @@ default CompletionStage<Void> lock(Object entity, LockModeType lockModeType) {
985987
*/
986988
MutationQuery createMutationQuery(JpaCriteriaInsert<?> insert);
987989

990+
/**
991+
* Create a typed {@link Query} instance for the given typed query reference.
992+
*
993+
* @param typedQueryReference the type query reference
994+
*
995+
* @return The {@link Query} instance for execution
996+
*
997+
* @throws IllegalArgumentException if a query has not been
998+
* defined with the name of the typed query reference or if
999+
* the query result is found to not be assignable to
1000+
* result class of the typed query reference
1001+
*
1002+
* @see org.hibernate.query.QueryProducer#createQuery(TypedQueryReference)
1003+
*/
1004+
<R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference);
1005+
9881006
/**
9891007
* Create an instance of {@link Query} for the given HQL/JPQL query
9901008
* string or HQL/JPQL update or delete statement. In the case of an
@@ -1637,6 +1655,22 @@ default <T> CompletionStage<T> get(Class<T> entityClass, Object id, LockModeType
16371655
@Deprecated
16381656
<R> Query<R> createQuery(String queryString);
16391657

1658+
/**
1659+
* Create a typed {@link Query} instance for the given typed query reference.
1660+
*
1661+
* @param typedQueryReference the type query reference
1662+
*
1663+
* @return The {@link Query} instance for execution
1664+
*
1665+
* @throws IllegalArgumentException if a query has not been
1666+
* defined with the name of the typed query reference or if
1667+
* the query result is found to not be assignable to
1668+
* result class of the typed query reference
1669+
*
1670+
* @see org.hibernate.query.QueryProducer#createQuery(TypedQueryReference)
1671+
*/
1672+
<R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference);
1673+
16401674
/**
16411675
* Create an instance of {@link SelectionQuery} for the given HQL/JPQL
16421676
* query string and query result type.

hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.hibernate.reactive.stage.impl;
77

8+
import jakarta.persistence.TypedQueryReference;
89
import java.lang.invoke.MethodHandles;
910
import java.util.List;
1011
import java.util.concurrent.CompletionStage;
@@ -26,6 +27,7 @@
2627
import org.hibernate.reactive.logging.impl.Log;
2728
import org.hibernate.reactive.logging.impl.LoggerFactory;
2829
import org.hibernate.reactive.pool.ReactiveConnection;
30+
import org.hibernate.reactive.query.ReactiveQuery;
2931
import org.hibernate.reactive.session.ReactiveConnectionSupplier;
3032
import org.hibernate.reactive.session.ReactiveQueryProducer;
3133
import org.hibernate.reactive.session.ReactiveSession;
@@ -530,6 +532,12 @@ public <T> EntityGraph<T> createEntityGraph(Class<T> rootType, String graphName)
530532
return delegate.createEntityGraph( rootType, graphName );
531533
}
532534

535+
@Override
536+
public <R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference) {
537+
ReactiveQuery<R> reactiveQuery = delegate.createReactiveQuery( typedQueryReference );
538+
return new StageQueryImpl<>( reactiveQuery );
539+
}
540+
533541
@Override @Deprecated
534542
public <R> Query<R> createQuery(String queryString) {
535543
return new StageQueryImpl<>( delegate.createReactiveQuery( queryString ) );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageStatelessSessionImpl.java

+8
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
import org.hibernate.query.criteria.JpaCriteriaInsert;
1111
import org.hibernate.reactive.common.ResultSetMapping;
1212
import org.hibernate.reactive.pool.ReactiveConnection;
13+
import org.hibernate.reactive.query.ReactiveQuery;
1314
import org.hibernate.reactive.session.ReactiveStatelessSession;
1415
import org.hibernate.reactive.stage.Stage;
1516
import org.hibernate.reactive.stage.Stage.MutationQuery;
1617
import org.hibernate.reactive.stage.Stage.Query;
1718
import org.hibernate.reactive.stage.Stage.SelectionQuery;
1819

1920
import jakarta.persistence.EntityGraph;
21+
import jakarta.persistence.TypedQueryReference;
2022
import jakarta.persistence.criteria.CriteriaDelete;
2123
import jakarta.persistence.criteria.CriteriaQuery;
2224
import jakarta.persistence.criteria.CriteriaUpdate;
@@ -289,6 +291,12 @@ public <R> Query<R> createQuery(String queryString) {
289291
return new StageQueryImpl<>( delegate.createReactiveQuery( queryString ) );
290292
}
291293

294+
@Override
295+
public <R> Query<R> createQuery(TypedQueryReference<R> typedQueryReference) {
296+
ReactiveQuery<R> reactiveQuery = delegate.createReactiveQuery( typedQueryReference );
297+
return new StageQueryImpl<>( reactiveQuery );
298+
}
299+
292300
@Override
293301
public <R> SelectionQuery<R> createSelectionQuery(String queryString, Class<R> resultType) {
294302
return new StageSelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString, resultType ) );

0 commit comments

Comments
 (0)