Skip to content

Commit ca535d7

Browse files
committed
HHH-19364 add support for fetching single-valued paths
1 parent 8b76686 commit ca535d7

File tree

9 files changed

+62
-1
lines changed

9 files changed

+62
-1
lines changed

hibernate-core/src/main/java/org/hibernate/query/programmatic/SelectionSpecification.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.query.Order;
1414
import org.hibernate.query.SelectionQuery;
1515
import org.hibernate.query.programmatic.internal.SelectionSpecificationImpl;
16+
import org.hibernate.query.restriction.Path;
1617
import org.hibernate.query.restriction.Restriction;
1718

1819
import java.util.List;
@@ -91,6 +92,15 @@ public interface SelectionSpecification<T> extends QuerySpecification<T> {
9192
@Override
9293
SelectionSpecification<T> addRestriction(Restriction<T> restriction);
9394

95+
/**
96+
* Add a fetch {@linkplain Path path} to the specification.
97+
*
98+
* @param fetchPath The path to fetch
99+
*
100+
* @return {@code this} for method chaining.
101+
*/
102+
SelectionSpecification<T> addFetching(Path<T,?> fetchPath);
103+
94104
@FunctionalInterface
95105
interface Mutator<T> {
96106
void mutate(CriteriaBuilder builder, CriteriaQuery<T> query, Root<T> root);

hibernate-core/src/main/java/org/hibernate/query/programmatic/internal/SelectionSpecificationImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.hibernate.query.Order;
1313
import org.hibernate.query.SelectionQuery;
1414
import org.hibernate.query.programmatic.SelectionSpecification;
15+
import org.hibernate.query.restriction.Path;
1516
import org.hibernate.query.restriction.Restriction;
1617
import org.hibernate.query.spi.HqlInterpretation;
1718
import org.hibernate.query.spi.QueryEngine;
@@ -78,6 +79,12 @@ public SelectionSpecification<T> mutate(Mutator<T> mutation) {
7879
return this;
7980
}
8081

82+
@Override
83+
public SelectionSpecification<T> addFetching(Path<T, ?> fetchPath) {
84+
specifications.add( (sqmStatement, root) -> fetchPath.fetch( root ) );
85+
return this;
86+
}
87+
8188
@Override
8289
public SelectionSpecification<T> addOrdering(Order<T> order) {
8390
specifications.add( (sqmStatement, root) -> {

hibernate-core/src/main/java/org/hibernate/query/restriction/NamedPathElement.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package org.hibernate.query.restriction;
66

77
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.criteria.FetchParent;
9+
810

911
/**
1012
* A non-root element of a {@link Path}, using a stringly-typed
@@ -28,4 +30,9 @@ public jakarta.persistence.criteria.Path<V> path(Root<? extends X> root) {
2830
}
2931
return path;
3032
}
33+
34+
@Override
35+
public FetchParent<?, ? extends V> fetch(Root<? extends X> root) {
36+
return parent.fetch( root ).fetch( attributeName );
37+
}
3138
}

hibernate-core/src/main/java/org/hibernate/query/restriction/Path.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.hibernate.query.restriction;
66

77
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.criteria.FetchParent;
89
import jakarta.persistence.metamodel.SingularAttribute;
910
import org.hibernate.Incubating;
1011
import org.hibernate.query.range.Range;
@@ -76,4 +77,6 @@ default Restriction<X> notIn(List<U> values) {
7677
default Restriction<X> notNull() {
7778
return restrict( Range.notNull( getType() ) );
7879
}
80+
81+
FetchParent<?, ? extends U> fetch(Root<? extends X> root);
7982
}

hibernate-core/src/main/java/org/hibernate/query/restriction/PathElement.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.hibernate.query.restriction;
66

77
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.criteria.FetchParent;
89
import jakarta.persistence.metamodel.SingularAttribute;
910

1011
/**
@@ -23,4 +24,9 @@ public Class<V> getType() {
2324
public jakarta.persistence.criteria.Path<V> path(Root<? extends X> root) {
2425
return parent.path( root ).get( attribute );
2526
}
27+
28+
@Override
29+
public FetchParent<?, ? extends V> fetch(Root<? extends X> root) {
30+
return parent.fetch( root ).fetch( attribute );
31+
}
2632
}

hibernate-core/src/main/java/org/hibernate/query/restriction/PathRoot.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.hibernate.query.restriction;
66

77
import jakarta.persistence.criteria.Root;
8+
import jakarta.persistence.criteria.FetchParent;
89

910
/**
1011
* A root element of a {@link Path}.
@@ -23,4 +24,9 @@ public jakarta.persistence.criteria.Path<X> path(Root<? extends X> root) {
2324
// unchecked cast only to get rid of the upper bound
2425
return (jakarta.persistence.criteria.Path<X>) root;
2526
}
27+
28+
@Override
29+
public FetchParent<?, ? extends X> fetch(Root<? extends X> root) {
30+
return root;
31+
}
2632
}

hibernate-core/src/test/java/org/hibernate/orm/test/query/dynamic/BasicEntity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import jakarta.persistence.Entity;
88
import jakarta.persistence.Id;
9+
import jakarta.persistence.ManyToOne;
910
import jakarta.persistence.Table;
1011

1112
/**
@@ -18,4 +19,7 @@ public class BasicEntity {
1819
private Integer id;
1920
private String name;
2021
private int position;
22+
23+
@ManyToOne
24+
OtherEntity other;
2125
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.query.dynamic;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.Table;
10+
11+
@Entity(name = "OtherEntity")
12+
@Table(name = "OtherEntity")
13+
public class OtherEntity {
14+
@Id
15+
private Integer id;
16+
}

hibernate-core/src/test/java/org/hibernate/orm/test/query/dynamic/SimpleQuerySpecificationTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hibernate.query.programmatic.MutationSpecification;
1212
import org.hibernate.query.programmatic.SelectionSpecification;
1313
import org.hibernate.query.range.Range;
14+
import org.hibernate.query.restriction.Path;
1415
import org.hibernate.query.restriction.Restriction;
1516
import org.hibernate.testing.jdbc.SQLStatementInspector;
1617
import org.hibernate.testing.orm.junit.DomainModel;
@@ -26,7 +27,7 @@
2627
* @author Steve Ebersole
2728
*/
2829
@SuppressWarnings("JUnitMalformedDeclaration")
29-
@DomainModel(annotatedClasses = BasicEntity.class)
30+
@DomainModel(annotatedClasses = {BasicEntity.class, OtherEntity.class})
3031
@org.hibernate.testing.orm.junit.SessionFactory(useCollectingStatementInspector = true)
3132
public class SimpleQuerySpecificationTests {
3233
@Test
@@ -184,6 +185,7 @@ void testCriteriaForm(SessionFactoryScope factoryScope) {
184185
query.where( criteriaBuilder.like( entity.get( BasicEntity_.name ), "%" ) );
185186
SelectionSpecification.create( query )
186187
.addOrdering( Order.asc( BasicEntity_.position ) )
188+
.addFetching( Path.from(BasicEntity.class).to( BasicEntity_.other ) )
187189
.createQuery( session )
188190
.getResultList();
189191
} );

0 commit comments

Comments
 (0)