Skip to content

Commit 8b64878

Browse files
committed
HHH-18990 introduce Path, allowing Restrictions on compound paths
1 parent ac0fbd7 commit 8b64878

File tree

22 files changed

+256
-2
lines changed

22 files changed

+256
-2
lines changed

documentation/src/main/asciidoc/introduction/Interacting.adoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,18 @@ Unfortunately, `Restriction` and `Order` can't be used with JPA's `TypedQuery` i
10851085

10861086
Alternatively, `Restriction` and `Order` can be used with <<paging-and-ordering,generated query or finder methods>>, and even with link:{doc-data-repositories-url}[Jakarta Data repositories].
10871087

1088+
The interface link:{doc-javadoc-url}org/hibernate/query/Path.html[`Path`] may be used to express restrictions on fields of an embedded or associated entity class.
1089+
1090+
[source,java]
1091+
----
1092+
List<Book> booksForPublisher =
1093+
session.createSelectionQuery("from Book", Book.class)
1094+
.addRestriction(Path.root(Book_.publisher)
1095+
.get(Publisher_.name)
1096+
.equalTo(publisherName))
1097+
.getResultList();
1098+
----
1099+
10881100
Programmatic restrictions, and especially programmatic ordering, are often used together with pagination.
10891101

10901102
[[pagination]]

hibernate-core/src/main/java/org/hibernate/query/AttributeRange.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*
1616
* @param <X> The entity type
1717
* @param <U> The attribute type
18+
*
19+
* @author Gavin King
1820
*/
1921
record AttributeRange<X, U>(SingularAttribute<X, U> attribute, Range<U> range) implements Restriction<X> {
2022
@Override

hibernate-core/src/main/java/org/hibernate/query/Conjunction.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*
1414
* @param restrictions The restrictions to be AND-ed
1515
* @param <X> The entity type
16+
*
17+
* @author Gavin King
1618
*/
1719
record Conjunction<X>(java.util.List<? extends Restriction<? super X>> restrictions)
1820
implements Restriction<X> {

hibernate-core/src/main/java/org/hibernate/query/Disjunction.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*
1414
* @param restrictions The restrictions to be OR-ed
1515
* @param <X> The entity type
16+
*
17+
* @author Gavin King
1618
*/
1719
record Disjunction<X>(java.util.List<? extends Restriction<? super X>> restrictions)
1820
implements Restriction<X> {

hibernate-core/src/main/java/org/hibernate/query/NamedAttributeRange.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*
1818
* @param <X> The entity type
1919
* @param <U> The attribute type
20+
*
21+
* @author Gavin King
2022
*/
2123
record NamedAttributeRange<X, U>(Class<X> entity, String attributeName, Range<U> range) implements Restriction<X> {
2224
@Override

hibernate-core/src/main/java/org/hibernate/query/Negation.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*
1414
* @param restriction The restriction to be negated
1515
* @param <X> The entity type
16+
*
17+
* @author Gavin King
1618
*/
1719
record Negation<X>(Restriction<X> restriction) implements Restriction<X> {
1820
@Override
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query;
6+
7+
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.metamodel.SingularAttribute;
9+
import org.hibernate.Incubating;
10+
import org.hibernate.query.range.Range;
11+
12+
import java.util.List;
13+
14+
/**
15+
* Allows construction of a {@link Restriction} on a compound path.
16+
* <p>
17+
* A compound path is a sequence of attribute references rooted at
18+
* the root entity type of the query.
19+
* <pre>
20+
* session.createSelectionQuery("from Book", Book.class)
21+
* .addRestriction(root(publisher).get(name).equalTo("Manning"))
22+
* .getResultList()
23+
* </pre>
24+
* A compound path-based restriction has the same semantics as the
25+
* equivalent implicit join in HQL.
26+
*
27+
* @param <X> The root entity type
28+
* @param <U> The leaf attribute type
29+
*
30+
* @see Restriction
31+
*
32+
* @author Gavin King
33+
*
34+
* @since 7.0
35+
*/
36+
@Incubating
37+
public interface Path<X,U> {
38+
jakarta.persistence.criteria.Path<U> path(Root<? extends X> root);
39+
40+
default <V> Path<X, V> get(SingularAttribute<? super U, V> attribute) {
41+
return new PathElement<>( this, attribute );
42+
}
43+
44+
static <X, U> Path<X, U> root(SingularAttribute<? super X, U> attribute) {
45+
return new PathRoot<X>().get( attribute );
46+
}
47+
48+
default Restriction<X> restrict(Range<U> range) {
49+
return new PathRange<>( this, range );
50+
}
51+
52+
default Restriction<X> equalTo(U value) {
53+
return restrict( Range.singleValue( value ) );
54+
}
55+
56+
default Restriction<X> notEqualTo(U value) {
57+
return equalTo( value ).negated();
58+
}
59+
60+
default Restriction<X> in(List<U> values) {
61+
return restrict( Range.valueList( values ) );
62+
}
63+
64+
default Restriction<X> notIn(List<U> values) {
65+
return in( values ).negated();
66+
}
67+
68+
//TODO: between, lessThan, greaterThan?
69+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query;
6+
7+
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.metamodel.SingularAttribute;
9+
10+
/**
11+
* A non-root element of a {@link Path}.
12+
*
13+
* @author Gavin King
14+
*/
15+
record PathElement<X, U, V>(Path<? super X, U> parent, SingularAttribute<? super U, V> attribute) implements Path<X, V> {
16+
@Override
17+
public jakarta.persistence.criteria.Path<V> path(Root<? extends X> root) {
18+
return parent.path( root ).get( attribute );
19+
}
20+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query;
6+
7+
import jakarta.persistence.criteria.CriteriaBuilder;
8+
import jakarta.persistence.criteria.Predicate;
9+
import jakarta.persistence.criteria.Root;
10+
import org.hibernate.query.range.Range;
11+
12+
/**
13+
* Restricts a path from an entity to a given {@link Range}.
14+
*
15+
* @param <X> The entity type
16+
* @param <U> The attribute type
17+
*
18+
* @author Gavin King
19+
*/
20+
record PathRange<X, U>(Path<X, U> path, Range<U> range) implements Restriction<X> {
21+
@Override
22+
public Restriction<X> negated() {
23+
return new Negation<>( this );
24+
}
25+
26+
@Override
27+
public Predicate toPredicate(Root<? extends X> root, CriteriaBuilder builder) {
28+
return range.toPredicate( path.path( root ), builder );
29+
}
30+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.query;
6+
7+
import jakarta.persistence.criteria.Root;
8+
9+
/**
10+
* A root element of a {@link Path}.
11+
*
12+
* @author Gavin King
13+
*/
14+
record PathRoot<X>() implements Path<X, X> {
15+
@Override
16+
@SuppressWarnings("unchecked")
17+
public jakarta.persistence.criteria.Path<X> path(Root<? extends X> root) {
18+
// unchecked cast only to get rid of the upper bound
19+
return (jakarta.persistence.criteria.Path<X>) root;
20+
}
21+
}

0 commit comments

Comments
 (0)