Skip to content

Commit b984f7d

Browse files
committed
HHH-19364 - Introduce simplified dynamic query builders
1 parent d503b63 commit b984f7d

20 files changed

+624
-478
lines changed

documentation/src/main/asciidoc/userguide/Hibernate_User_Guide.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ include::chapters/caching/Caching.adoc[]
3131
include::chapters/events/Events.adoc[]
3232
include::chapters/query/hql/Query.adoc[]
3333
include::chapters/query/hql/QueryLanguage.adoc[]
34-
include::chapters/query/dynamic/DynamicQueries.adoc[]
34+
include::chapters/query/programmatic/QuerySpecification.adoc[]
3535
include::chapters/query/criteria/Criteria.adoc[]
3636
include::chapters/query/criteria/CriteriaExtensions.adoc[]
3737
include::chapters/query/native/Native.adoc[]

documentation/src/main/asciidoc/userguide/chapters/query/dynamic/DynamicQueries.adoc

-98
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
[[QuerySpecification]]
2+
== Programmatic Query Specification
3+
:root-project-dir: ../../../../../../../..
4+
5+
Hibernate offers an API for creating dynamic representations of a query, adjusting that representation and then creating an executable form of the query. The idea is similar in concept to <<chapters/query/criteria/Criteria.adoc#criteria,criteria queries>>, but focused on ease-of-use and less verbosity.
6+
7+
There is support for both <<SelectionSpecification,selection>> and <<MutationSpecification,mutation>> queries via the `SelectionSpecification` and `MutationSpecification` contracts, respectively. These can be obtained from both `Session` and `StatelessSession`.
8+
9+
[NOTE]
10+
====
11+
These APIs are new in 7.0 and considered incubating.
12+
====
13+
14+
[[SelectionSpecification]]
15+
=== SelectionSpecification
16+
17+
A `SelectionSpecification` allows to iteratively build a query from a "base", adjust the query by adding sorting and restrictions and finally creating an executable <<hql-SelectionQuery,`SelectionQuery`>>. We can use HQL as the base -
18+
19+
.SelectionSpecification from HQL
20+
====
21+
[source, java, indent=0]
22+
----
23+
SelectionSpecification<Book> spec = session.createSelectionSpecification(
24+
"from Book",
25+
Book.class
26+
);
27+
----
28+
====
29+
30+
or a root entity as the base -
31+
32+
.SelectionSpecification from root entity
33+
====
34+
[source, java, indent=0]
35+
----
36+
SelectionSpecification<Book> spec = session.createSelectionSpecification(Book.class);
37+
----
38+
====
39+
40+
Once we have the `SelectionSpecification` we can adjust the query adding restrictions and sorting -
41+
42+
.Adjusting the SelectionSpecification
43+
====
44+
[source, java, indent=0]
45+
----
46+
// from here we can augment the base query "from Book",
47+
// with either restrictions
48+
spec.restriction(
49+
Restriction.restrict(
50+
Book_.suggestedCost,
51+
Range.closed(10.00, 19.99)
52+
)
53+
);
54+
55+
// or here with some sorting
56+
spec.order(
57+
Order.asc(Book_.suggestedCost)
58+
)
59+
----
60+
====
61+
62+
[NOTE]
63+
====
64+
Notice that generally the JPA static metamodel is a convenient and type-safe way to help build these sorting and restriction references.
65+
====
66+
67+
After adjusting the query, we can obtain the executable `SelectionQuery`:
68+
69+
.Using the SelectionSpecification
70+
====
71+
[source, java, indent=0]
72+
----
73+
SelectionQuery<Book> qry = ds.createQuery();
74+
List<Book> books = qry.getResultList();
75+
----
76+
====
77+
78+
These calls can even be chained, e.g.
79+
80+
====
81+
[source, java, indent=0]
82+
----
83+
SelectionQuery<Book> qry = session.createSelectionSpecification(
84+
"from Book",
85+
Book.class
86+
).restriction(
87+
Restriction.restrict(
88+
Book_.suggestedCost,
89+
Range.closed(10.00, 19.99)
90+
)
91+
).order(
92+
Order.asc(Book_.suggestedCost)
93+
).createQuery();
94+
----
95+
====
96+
97+
[NOTE]
98+
====
99+
We expect, in future releases, to add the ability to handle pagination.
100+
101+
We also expect to add the ability to use <<criteria,Criteria>> references as the base. Possibly even `TypedQueryReference` references.
102+
====
103+
104+
[[MutationSpecification]]
105+
=== MutationSpecification
106+
107+
There is also support for mutation queries through `MutationSpecification`.
108+
At the moment, only update and delete queries are supported. E.g.
109+
110+
.MutationQuery example
111+
====
112+
[source, java, indent=0]
113+
----
114+
MutationQuery<Book> qry = session.createMutationSpecification(
115+
"delete Book",
116+
Book.class
117+
).restriction(
118+
Restriction.restrict(
119+
Book_.suggestedCost,
120+
Range.closed(10.00, 19.99)
121+
)
122+
).createQuery();
123+
----
124+
====

hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java

+34-30
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,23 @@
44
*/
55
package org.hibernate.engine.spi;
66

7-
import java.util.Collection;
8-
import java.util.List;
9-
import java.util.Map;
10-
import java.util.Set;
11-
import java.util.TimeZone;
12-
import java.util.UUID;
13-
7+
import jakarta.persistence.CacheRetrieveMode;
8+
import jakarta.persistence.CacheStoreMode;
9+
import jakarta.persistence.EntityGraph;
10+
import jakarta.persistence.EntityManagerFactory;
11+
import jakarta.persistence.FindOption;
12+
import jakarta.persistence.FlushModeType;
13+
import jakarta.persistence.LockModeType;
14+
import jakarta.persistence.LockOption;
15+
import jakarta.persistence.RefreshOption;
16+
import jakarta.persistence.TypedQueryReference;
17+
import jakarta.persistence.criteria.CriteriaDelete;
18+
import jakarta.persistence.criteria.CriteriaQuery;
19+
import jakarta.persistence.criteria.CriteriaSelect;
20+
import jakarta.persistence.criteria.CriteriaUpdate;
1421
import jakarta.persistence.metamodel.EntityType;
22+
import jakarta.persistence.metamodel.Metamodel;
23+
import org.checkerframework.checker.nullness.qual.Nullable;
1524
import org.hibernate.CacheMode;
1625
import org.hibernate.Filter;
1726
import org.hibernate.FlushMode;
@@ -46,36 +55,26 @@
4655
import org.hibernate.persister.entity.EntityPersister;
4756
import org.hibernate.procedure.ProcedureCall;
4857
import org.hibernate.query.MutationQuery;
49-
import org.hibernate.query.DynamicMutation;
5058
import org.hibernate.query.SelectionQuery;
51-
import org.hibernate.query.DynamicSelection;
5259
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
5360
import org.hibernate.query.criteria.JpaCriteriaInsert;
61+
import org.hibernate.query.programmatic.MutationSpecification;
62+
import org.hibernate.query.programmatic.SelectionSpecification;
5463
import org.hibernate.query.spi.QueryImplementor;
5564
import org.hibernate.query.spi.QueryProducerImplementor;
5665
import org.hibernate.query.sql.spi.NativeQueryImplementor;
5766
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
5867
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
5968
import org.hibernate.stat.SessionStatistics;
60-
61-
import jakarta.persistence.CacheRetrieveMode;
62-
import jakarta.persistence.CacheStoreMode;
63-
import jakarta.persistence.EntityGraph;
64-
import jakarta.persistence.EntityManagerFactory;
65-
import jakarta.persistence.FindOption;
66-
import jakarta.persistence.FlushModeType;
67-
import jakarta.persistence.LockModeType;
68-
import jakarta.persistence.LockOption;
69-
import jakarta.persistence.RefreshOption;
70-
import jakarta.persistence.TypedQueryReference;
71-
import jakarta.persistence.criteria.CriteriaDelete;
72-
import jakarta.persistence.criteria.CriteriaQuery;
73-
import jakarta.persistence.criteria.CriteriaSelect;
74-
import jakarta.persistence.criteria.CriteriaUpdate;
75-
import jakarta.persistence.metamodel.Metamodel;
76-
import org.checkerframework.checker.nullness.qual.Nullable;
7769
import org.hibernate.type.format.FormatMapper;
7870

71+
import java.util.Collection;
72+
import java.util.List;
73+
import java.util.Map;
74+
import java.util.Set;
75+
import java.util.TimeZone;
76+
import java.util.UUID;
77+
7978
/**
8079
* A wrapper class that delegates all method invocations to a delegate instance of
8180
* {@link SessionImplementor}. This is useful for custom implementations of that
@@ -659,13 +658,18 @@ public MutationQuery createNamedMutationQuery(String name) {
659658
}
660659

661660
@Override
662-
public <T> DynamicSelection<T> createDynamicSelection(String hql, Class<T> resultType) {
663-
return delegate.createDynamicSelection( hql, resultType );
661+
public <T> SelectionSpecification<T> createSelectionSpecification(String hql, Class<T> resultType) {
662+
return delegate.createSelectionSpecification( hql, resultType );
663+
}
664+
665+
@Override
666+
public <T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootEntityType) {
667+
return delegate.createSelectionSpecification( rootEntityType );
664668
}
665669

666670
@Override
667-
public <T> DynamicMutation<T> createDynamicMutation(String hql, Class<T> mutationTarget) {
668-
return delegate.createDynamicMutation( hql, mutationTarget );
671+
public <T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget) {
672+
return delegate.createMutationSpecification( hql, mutationTarget );
669673
}
670674

671675
@Override

0 commit comments

Comments
 (0)