Skip to content

Commit aa08c5a

Browse files
committed
[hibernate#1735] First changes for setOrder() support
1 parent 40d08dd commit aa08c5a

File tree

11 files changed

+347
-2
lines changed

11 files changed

+347
-2
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ org.gradle.java.installations.auto-download=false
2222
##########################################################################
2323

2424
# Enable Testcontainers + Docker when present (value ignored)
25-
#docker = true
25+
docker = true
2626

2727
# The database type to use (key insensitive and support aliases):
2828
# Db2, MySql, PostgreSQL, CockroachDB, SqlServer, Oracle
29-
#db = MSSQL
29+
db = PostgreSQL
3030

3131
# Enable the SonatypeOS maven repository (mainly for Vert.x snapshots) when present (value ignored)
3232
#enableSonatypeOpenSourceSnapshotsRep = true

hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.hibernate.graph.spi.RootGraphImplementor;
2323
import org.hibernate.query.BindableType;
2424
import org.hibernate.query.CommonQueryContract;
25+
import org.hibernate.query.Order;
2526
import org.hibernate.query.QueryParameter;
2627

2728
import jakarta.persistence.CacheRetrieveMode;
@@ -123,6 +124,10 @@ default CompletionStage<List<R>> getReactiveResultList() {
123124

124125
void applyGraph(RootGraphImplementor<?> graph, GraphSemantic semantic);
125126

127+
ReactiveSelectionQuery<R> setOrder(List<Order<? super R>> orderList);
128+
129+
ReactiveSelectionQuery<R> setOrder(Order<? super R> order);
130+
126131
ReactiveSelectionQuery<R> enableFetchProfile(String profileName);
127132

128133
@Override

hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.hibernate.internal.AbstractSharedSessionContract;
3030
import org.hibernate.metamodel.model.domain.BasicDomainType;
3131
import org.hibernate.query.BindableType;
32+
import org.hibernate.query.Order;
3233
import org.hibernate.query.QueryParameter;
3334
import org.hibernate.query.ResultListTransformer;
3435
import org.hibernate.query.TupleTransformer;
@@ -473,6 +474,18 @@ public ReactiveNativeQueryImpl<R> setLockMode(String alias, LockMode lockMode) {
473474
return this;
474475
}
475476

477+
@Override
478+
public ReactiveNativeQueryImpl<R> setOrder(List<Order<? super R>> orders) {
479+
super.setOrder( orders );
480+
return this;
481+
}
482+
483+
@Override
484+
public ReactiveNativeQueryImpl<R> setOrder(Order<? super R> order) {
485+
super.setOrder( order );
486+
return this;
487+
}
488+
476489
@Override
477490
public ReactiveNativeQueryImpl<R> setComment(String comment) {
478491
super.setComment( comment );

hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/ReactiveSqmSelectionQuery.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@
99
import java.util.Calendar;
1010
import java.util.Collection;
1111
import java.util.Date;
12+
import java.util.List;
1213
import java.util.Map;
1314

1415
import org.hibernate.CacheMode;
1516
import org.hibernate.FlushMode;
1617
import org.hibernate.query.BindableType;
18+
import org.hibernate.query.Order;
1719
import org.hibernate.query.QueryParameter;
1820
import org.hibernate.query.spi.SqmQuery;
1921
import org.hibernate.reactive.query.ReactiveSelectionQuery;
22+
import org.hibernate.reactive.query.sqm.internal.ReactiveSqmSelectionQueryImpl;
2023

2124
import jakarta.persistence.Parameter;
2225
import jakarta.persistence.TemporalType;
@@ -167,6 +170,10 @@ <P> ReactiveSqmSelectionQuery<R> setParameterList(
167170
@Override
168171
ReactiveSqmSelectionQuery<R> setTimeout(int timeout);
169172

173+
ReactiveSqmSelectionQueryImpl<R> setOrder(List<Order<? super R>> orders);
174+
175+
ReactiveSqmSelectionQueryImpl<R> setOrder(Order<? super R> order);
176+
170177
@Override
171178
ReactiveSqmSelectionQuery<R> setFetchSize(int fetchSize);
172179

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.hibernate.persister.entity.EntityPersister;
3636
import org.hibernate.query.BindableType;
3737
import org.hibernate.query.IllegalQueryOperationException;
38+
import org.hibernate.query.Order;
3839
import org.hibernate.query.QueryParameter;
3940
import org.hibernate.query.ResultListTransformer;
4041
import org.hibernate.query.TupleTransformer;
@@ -459,6 +460,18 @@ public ReactiveQuerySqmImpl<R> setLockMode(String alias, LockMode lockMode) {
459460
return this;
460461
}
461462

463+
@Override
464+
public ReactiveQuerySqmImpl<R> setOrder(List<Order<? super R>> orders) {
465+
super.setOrder( orders );
466+
return this;
467+
}
468+
469+
@Override
470+
public ReactiveQuerySqmImpl<R> setOrder(Order<? super R> order) {
471+
super.setOrder( order );
472+
return this;
473+
}
474+
462475
@Override
463476
public <T> ReactiveQuerySqmImpl<T> setTupleTransformer(TupleTransformer<T> transformer) {
464477
throw new UnsupportedOperationException();

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.hibernate.graph.spi.RootGraphImplementor;
2727
import org.hibernate.internal.util.collections.IdentitySet;
2828
import org.hibernate.query.BindableType;
29+
import org.hibernate.query.Order;
2930
import org.hibernate.query.QueryLogging;
3031
import org.hibernate.query.QueryParameter;
3132
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
@@ -251,6 +252,17 @@ public ReactiveSqmSelectionQueryImpl<R> setFollowOnLocking(boolean enable) {
251252
return this;
252253
}
253254

255+
public ReactiveSqmSelectionQueryImpl<R> setOrder(List<Order<? super R>> orders) {
256+
super.setOrder( orders );
257+
return this;
258+
}
259+
260+
@Override
261+
public ReactiveSqmSelectionQueryImpl<R> setOrder(Order<? super R> order) {
262+
super.setOrder( order );
263+
return this;
264+
}
265+
254266
@Override
255267
public ReactiveSqmSelectionQueryImpl<R> setFetchSize(int fetchSize) {
256268
super.setFetchSize( fetchSize );

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
import org.hibernate.engine.spi.SharedSessionContractImplementor;
2828
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
2929
import org.hibernate.proxy.HibernateProxy;
30+
import org.hibernate.query.Order;
3031
import org.hibernate.query.Page;
32+
import org.hibernate.query.SelectionQuery;
3133
import org.hibernate.reactive.common.AffectedEntities;
3234
import org.hibernate.reactive.common.Identifier;
3335
import org.hibernate.reactive.common.ResultSetMapping;
@@ -347,6 +349,32 @@ default SelectionQuery<R> setLockMode(String alias, LockModeType lockModeType) {
347349
// */
348350
// Query<R> setLockOptions(LockOptions lockOptions);
349351

352+
/**
353+
* If the result type of this query is an entity class, add one or more
354+
* {@linkplain Order rules} for ordering the query results.
355+
*
356+
* @param orderList one or more instances of {@link Order}
357+
*
358+
* @see Order
359+
*
360+
* @see org.hibernate.query.Query#setOrder(List)
361+
*/
362+
@Incubating
363+
SelectionQuery<R> setOrder(List<Order<? super R>> orderList);
364+
365+
/**
366+
* If the result type of this query is an entity class, add a
367+
* {@linkplain Order rule} for ordering the query results.
368+
*
369+
* @param order an instance of {@link Order}
370+
*
371+
* @see Order
372+
*
373+
* @see org.hibernate.query.Query#setOrder(Order)
374+
*/
375+
@Incubating
376+
SelectionQuery<R> setOrder(Order<? super R> order);
377+
350378
/**
351379
* Set the {@link EntityGraph} that will be used as a fetch plan for
352380
* the root entity returned by this query.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.LockMode;
1414
import org.hibernate.graph.GraphSemantic;
1515
import org.hibernate.graph.spi.RootGraphImplementor;
16+
import org.hibernate.query.Order;
1617
import org.hibernate.query.Page;
1718
import org.hibernate.reactive.query.ReactiveQuery;
1819
import org.hibernate.reactive.stage.Stage;
@@ -59,6 +60,18 @@ public Query<R> setLockMode(LockMode lockMode) {
5960
return this;
6061
}
6162

63+
@Override
64+
public Stage.SelectionQuery<R> setOrder(List<Order<? super R>> orders) {
65+
delegate.setOrder( orders );
66+
return this;
67+
}
68+
69+
@Override
70+
public Stage.SelectionQuery<R> setOrder(Order<? super R> order) {
71+
delegate.setOrder( (List<Order<? super R>>) order );
72+
return this;
73+
}
74+
6275
@Override
6376
public Query<R> setPlan(EntityGraph<R> entityGraph) {
6477
delegate.applyGraph( (RootGraphImplementor<?>) entityGraph, GraphSemantic.FETCH );

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.hibernate.reactive.stage.impl;
77

8+
import java.lang.invoke.MethodHandles;
89
import java.util.List;
910
import java.util.concurrent.CompletionStage;
1011

@@ -13,7 +14,10 @@
1314
import org.hibernate.LockMode;
1415
import org.hibernate.graph.GraphSemantic;
1516
import org.hibernate.graph.spi.RootGraphImplementor;
17+
import org.hibernate.query.Order;
1618
import org.hibernate.query.Page;
19+
import org.hibernate.reactive.logging.impl.Log;
20+
import org.hibernate.reactive.logging.impl.LoggerFactory;
1721
import org.hibernate.reactive.query.ReactiveSelectionQuery;
1822
import org.hibernate.reactive.stage.Stage.SelectionQuery;
1923

@@ -24,7 +28,9 @@
2428
import jakarta.persistence.LockModeType;
2529
import jakarta.persistence.Parameter;
2630

31+
2732
public class StageSelectionQueryImpl<T> implements SelectionQuery<T> {
33+
private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() );
2834
private final ReactiveSelectionQuery<T> delegate;
2935

3036
public StageSelectionQueryImpl(ReactiveSelectionQuery<T> delegate) {
@@ -188,6 +194,29 @@ public SelectionQuery<T> setLockMode(String alias, LockMode lockMode) {
188194
return this;
189195
}
190196

197+
@Override
198+
public SelectionQuery<T> setOrder(List<Order<? super T>> orders) {
199+
throw LOG.notYetImplemented();
200+
// TODO: see org.hibernate.query.sqm.internal.SqmSelectQueryImpl#setOrder()
201+
// sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
202+
// sqm.orderBy( orderList.stream().map( order -> sortSpecification( sqm, order ) )
203+
// .collect( toList() ) );
204+
// // TODO: when the QueryInterpretationCache can handle caching criteria queries,
205+
// // simply cache the new SQM as if it were a criteria query, and remove this:
206+
// getQueryOptions().setQueryPlanCachingEnabled( false );
207+
// return this;
208+
}
209+
210+
@Override
211+
public SelectionQuery<T> setOrder(Order<? super T> order) {
212+
throw LOG.notYetImplemented();
213+
// TODO: see org.hibernate.query.sqm.internal.SqmSelectQueryImpl#setOrder()
214+
// SqmSelectStatement sqm = (SqmSelectStatement) (( SqmSelectionQuery )this).getSqmStatement().copy( SqmCopyContext.noParamCopyContext() );
215+
// sqm.orderBy( (( SqmSelectionQuery )this).sortSpecification( sqm, order ) );
216+
// getQueryOptions().setQueryPlanCachingEnabled( false );
217+
// return this;
218+
}
219+
191220
@Override
192221
public SelectionQuery<T> setParameter(String name, Object value) {
193222
delegate.setParameter( name, value );
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.orderby;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
import java.util.concurrent.CompletionStage;
11+
12+
import org.hibernate.metamodel.model.domain.EntityDomainType;
13+
import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl;
14+
import org.hibernate.query.Order;
15+
import org.hibernate.reactive.BaseReactiveTest;
16+
import org.hibernate.reactive.util.impl.CompletionStages;
17+
18+
import org.junit.jupiter.api.Test;
19+
20+
import io.vertx.junit5.Timeout;
21+
import io.vertx.junit5.VertxTestContext;
22+
import jakarta.persistence.Entity;
23+
import jakarta.persistence.Id;
24+
import jakarta.persistence.metamodel.SingularAttribute;
25+
26+
import static java.util.concurrent.TimeUnit.MINUTES;
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
import static org.junit.jupiter.api.Assertions.assertTrue;
29+
30+
// TODO: Started this test class based on org.hibernate.orm.test.query.order.OrderTest
31+
// Changes required:
32+
// - implement "setOrder(...)" methods for reactive session class as well as reactive SelectionQuery classes
33+
// - ORM test relies on finding the "SingularAttribute" type for an element in order to call
34+
// "import static org.hibernate.query.Order.asc;"
35+
// "import static org.hibernate.query.Order.desc;"
36+
//
37+
@Timeout(value = 10, timeUnit = MINUTES)
38+
public class OrderTest extends BaseReactiveTest {
39+
final Book book1 = new Book("9781932394153", "Hibernate in Action");
40+
final Book book2 = new Book("9781617290459", "Java Persistence with Hibernate");
41+
42+
43+
@Override
44+
protected Collection<Class<?>> annotatedEntities() {
45+
return List.of(
46+
Book.class
47+
);
48+
}
49+
50+
@Override
51+
protected CompletionStage<Void> cleanDb() {
52+
return CompletionStages.voidFuture();
53+
}
54+
55+
private CompletionStage<Void> populateDB() {
56+
return getSessionFactory()
57+
.withTransaction( session -> session.persist( book1, book2 ) );
58+
}
59+
60+
@Test
61+
public void testOrder(VertxTestContext context) {
62+
test(
63+
context,
64+
populateDB().thenCompose( v -> getSessionFactory()
65+
.withTransaction( (session, tx) -> session
66+
.createSelectionQuery( "select title from Book", String.class )
67+
.getResultList()
68+
.thenAccept( list -> assertTrue( list.size() == 2 ) )
69+
.thenCompose( vv -> {
70+
MappingMetamodelImpl metamodel = (MappingMetamodelImpl) getSessionFactory().getMetamodel();
71+
EntityDomainType<Book> bookType = metamodel.getJpaMetamodel()
72+
.findEntityType( Book.class );
73+
SingularAttribute<? super Book, ?> title = bookType.findSingularAttribute( "title" );
74+
SingularAttribute<? super Book, ?> isbn = bookType.findSingularAttribute( "isbn" );
75+
return session
76+
.createSelectionQuery( "from Book", Book.class )
77+
.setOrder( Order.asc( title ) )
78+
.getResultList();
79+
} ).thenAccept( books -> {
80+
assertEquals( "Hibernate in Action", books.get( 0 ).title );
81+
assertEquals( "Java Persistence with Hibernate", books.get( 1 ).title );
82+
} )
83+
) )
84+
);
85+
86+
}
87+
88+
@Entity(name="Book")
89+
static class Book {
90+
@Id
91+
String isbn;
92+
String title;
93+
94+
Book(String isbn, String title) {
95+
this.isbn = isbn;
96+
this.title = title;
97+
}
98+
99+
Book() {
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)