Skip to content

Commit d306aad

Browse files
committed
HHH-18517 allow composition of CriteriaDefinitions
Signed-off-by: Gavin King <[email protected]>
1 parent 4fd9a4f commit d306aad

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import org.hibernate.query.SelectionQuery;
1919
import org.hibernate.query.criteria.spi.HibernateCriteriaBuilderDelegate;
2020
import org.hibernate.query.sqm.FetchClauseType;
21+
import org.hibernate.query.sqm.tree.SqmCopyContext;
22+
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
2123

2224
import java.util.Collection;
2325
import java.util.List;
@@ -85,6 +87,28 @@
8587
* ...
8688
* });
8789
* </pre>
90+
* A {@code CriteriaDefinition} may be used to modify another {@code CriteriaDefinition}:
91+
* <pre>
92+
* var bookFilter
93+
* = new CriteriaDefinition&lt;&gt;(sessionFactory, Book.class) {{
94+
* where(like(from(Book.class).get(Book_.title), "%Hibernate%"));
95+
* }};
96+
* long count
97+
* = new CriteriaDefinition&lt;&gt;(bookFilter, Long.class) {{
98+
* select(count());
99+
* }}
100+
* .createSelectionQuery(session)
101+
* .getSingleResult();
102+
* var books =
103+
* = new CriteriaDefinition&lt;&gt;(bookFilter) {{
104+
* var book = (Root&lt;Book&gt;) getRootList().get(0);
105+
* book.fetch(Book_.authors);
106+
* orderBy(desc(book.get(Book_.publicationDate)), asc(book.get(Book_.isbn)));
107+
* }}
108+
* .createSelectionQuery(session)
109+
* .setMaxResults(10)
110+
* .getResultList();
111+
* </pre>
88112
*
89113
* @param <R> the query result type
90114
*
@@ -99,6 +123,37 @@ public abstract class CriteriaDefinition<R>
99123

100124
private final JpaCriteriaQuery<R> query;
101125

126+
/**
127+
* Construct a new {@code CriteriaDefinition} based on the given
128+
* {@code CriteriaDefinition}, with the same query return type.
129+
*
130+
* @param template the original query
131+
*
132+
* @since 7.0
133+
*/
134+
public CriteriaDefinition(CriteriaDefinition<R> template) {
135+
super( template.getCriteriaBuilder() );
136+
query = ((SqmSelectStatement<R>) template.query)
137+
.copy( SqmCopyContext.simpleContext() );
138+
}
139+
140+
/**
141+
* Construct a new {@code CriteriaDefinition} based on the given
142+
* {@code CriteriaDefinition}. This overload permits changing the
143+
* query return type. It is expected that {@link #select} be called
144+
* to rewrite the selection list.
145+
*
146+
* @param template the original query
147+
* @param resultType the new return type
148+
*
149+
* @since 7.0
150+
*/
151+
public CriteriaDefinition(CriteriaDefinition<?> template, Class<R> resultType) {
152+
super( template.getCriteriaBuilder() );
153+
query = ((SqmSelectStatement<?>) template.query)
154+
.createCopy( SqmCopyContext.simpleContext(), resultType );
155+
}
156+
102157
public CriteriaDefinition(SessionFactory factory, Class<R> resultType) {
103158
super( factory.getCriteriaBuilder() );
104159
query = createQuery( resultType );

hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.Set;
1414
import java.util.stream.Collectors;
1515

16+
import org.hibernate.Internal;
1617
import org.hibernate.query.criteria.JpaCriteriaQuery;
1718
import org.hibernate.query.criteria.JpaExpression;
1819
import org.hibernate.query.criteria.JpaSelection;
@@ -26,8 +27,6 @@
2627
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
2728
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
2829
import org.hibernate.query.sqm.tree.expression.SqmParameter;
29-
import org.hibernate.query.sqm.tree.expression.SqmStar;
30-
import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter;
3130
import org.hibernate.query.sqm.tree.from.SqmFromClause;
3231
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
3332
import org.hibernate.query.sqm.tree.from.SqmRoot;
@@ -127,7 +126,8 @@ public SqmSelectStatement<T> copy(SqmCopyContext context) {
127126
return createCopy( context, getResultType() );
128127
}
129128

130-
private <X> SqmSelectStatement<X> createCopy(SqmCopyContext context, Class<X> resultType) {
129+
@Internal
130+
public <X> SqmSelectStatement<X> createCopy(SqmCopyContext context, Class<X> resultType) {
131131
final Set<SqmParameter<?>> parameters;
132132
if ( this.parameters == null ) {
133133
parameters = null;

hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/query/CriteriaDefinitionTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ public class CriteriaDefinitionTest {
5454
orderBy(asc(message.get("id")));
5555
}};
5656

57+
var query5 = new CriteriaDefinition<>(query4, Long.class) {{
58+
select(count());
59+
orderBy();
60+
}};
61+
5762
scope.inSession(session -> {
5863
var idAndText = session.createSelectionQuery(query1).getSingleResult();
5964
assertNotNull(idAndText);
@@ -72,6 +77,9 @@ public class CriteriaDefinitionTest {
7277
assertNotNull(msg);
7378
assertEquals(1L,msg.id);
7479
assertEquals("hello",msg.text);
80+
81+
long count = session.createSelectionQuery(query5).getSingleResult();
82+
assertEquals(1L,count);
7583
});
7684
}
7785

0 commit comments

Comments
 (0)