Skip to content

Commit b1705bc

Browse files
committed
add convenience createProjection() methods
1 parent bab230b commit b1705bc

File tree

2 files changed

+57
-11
lines changed

2 files changed

+57
-11
lines changed

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

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
*/
55
package org.hibernate.query.specification;
66

7-
import jakarta.persistence.TypedQueryReference;
87
import jakarta.persistence.EntityManager;
9-
import jakarta.persistence.criteria.CriteriaQuery;
8+
import jakarta.persistence.TypedQueryReference;
109
import jakarta.persistence.criteria.CriteriaBuilder;
10+
import jakarta.persistence.criteria.CriteriaQuery;
1111
import jakarta.persistence.criteria.Root;
12+
import jakarta.persistence.metamodel.SingularAttribute;
1213

1314
import org.hibernate.Incubating;
1415
import org.hibernate.Session;
@@ -17,9 +18,9 @@
1718
import org.hibernate.query.Order;
1819
import org.hibernate.query.Page;
1920
import org.hibernate.query.SelectionQuery;
20-
import org.hibernate.query.specification.internal.SelectionSpecificationImpl;
2121
import org.hibernate.query.restriction.Path;
2222
import org.hibernate.query.restriction.Restriction;
23+
import org.hibernate.query.specification.internal.SelectionSpecificationImpl;
2324

2425
import java.util.List;
2526

@@ -242,4 +243,50 @@ static <T> SelectionSpecification<T> create(Class<T> resultType, String hql) {
242243
static <T> SelectionSpecification<T> create(CriteriaQuery<T> criteria) {
243244
return new SelectionSpecificationImpl<>( criteria );
244245
}
246+
247+
/**
248+
* Create a {@link ProjectionSpecification} allowing selection of specific
249+
* {@linkplain ProjectionSpecification#select(SingularAttribute) fields}
250+
* and {@linkplain ProjectionSpecification#select(Path) compound paths}.
251+
* The returned projection holds a reference to this specification,
252+
* and so mutation of this object also affects the projection.
253+
*
254+
* @return a new {@link ProjectionSpecification}
255+
*
256+
* @since 7.2
257+
*/
258+
@Incubating
259+
default ProjectionSpecification<T> createProjection() {
260+
return ProjectionSpecification.create( this );
261+
}
262+
263+
/**
264+
* Create a {@link SimpleProjectionSpecification} for the given
265+
* {@linkplain ProjectionSpecification#select(SingularAttribute) field}.
266+
* The returned projection holds a reference to this specification,
267+
* and so mutation of this object also affects the projection.
268+
*
269+
* @return a new {@link SimpleProjectionSpecification}
270+
*
271+
* @since 7.2
272+
*/
273+
@Incubating
274+
default <X> SimpleProjectionSpecification<T,X> createProjection(SingularAttribute<? super T, X> attribute) {
275+
return SimpleProjectionSpecification.create( this, attribute );
276+
}
277+
278+
/**
279+
* Create a {@link SimpleProjectionSpecification} for the given
280+
* {@linkplain ProjectionSpecification#select(Path) compound path}.
281+
* The returned projection holds a reference to this specification,
282+
* and so mutation of this object also affects the projection.
283+
*
284+
* @return a new {@link SimpleProjectionSpecification}
285+
*
286+
* @since 7.2
287+
*/
288+
@Incubating
289+
default <X> SimpleProjectionSpecification<T,X> createProjection(Path<T, X> path) {
290+
return SimpleProjectionSpecification.create( this, path );
291+
}
245292
}

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
package org.hibernate.orm.test.query.dynamic;
66

77
import org.hibernate.query.restriction.Path;
8-
import org.hibernate.query.specification.ProjectionSpecification;
98
import org.hibernate.query.specification.SelectionSpecification;
10-
import org.hibernate.query.specification.SimpleProjectionSpecification;
119
import org.hibernate.testing.orm.junit.DomainModel;
1210
import org.hibernate.testing.orm.junit.SessionFactoryScope;
1311
import org.junit.jupiter.api.BeforeAll;
@@ -36,7 +34,7 @@ public static void setup(SessionFactoryScope factoryScope) {
3634
void testProjection(SessionFactoryScope factoryScope) {
3735
factoryScope.inTransaction( (session) -> {
3836
var spec = SelectionSpecification.create( BasicEntity.class );
39-
var projection = ProjectionSpecification.create( spec );
37+
var projection = spec.createProjection();
4038
var position = projection.select( BasicEntity_.position );
4139
var name = projection.select( BasicEntity_.name );
4240
var id = projection.select( Path.from( BasicEntity.class ).to( BasicEntity_.id ) );
@@ -53,7 +51,7 @@ void testProjection(SessionFactoryScope factoryScope) {
5351
void testSimpleProjection(SessionFactoryScope factoryScope) {
5452
factoryScope.inTransaction( (session) -> {
5553
var spec = SelectionSpecification.create( BasicEntity.class );
56-
var projection = SimpleProjectionSpecification.create( spec, BasicEntity_.name );
54+
var projection = spec.createProjection( BasicEntity_.name );
5755
var name = projection.createQuery( session ).getSingleResult();
5856
assertEquals( "Gavin", name );
5957
});
@@ -63,10 +61,11 @@ void testSimpleProjection(SessionFactoryScope factoryScope) {
6361
void testSimpleProjectionPath(SessionFactoryScope factoryScope) {
6462
factoryScope.inTransaction( (session) -> {
6563
var spec = SelectionSpecification.create( BasicEntity.class );
66-
var projection = SimpleProjectionSpecification.create( spec,
67-
Path.from( BasicEntity.class)
68-
.to( BasicEntity_.other )
69-
.to( OtherEntity_.id ) );
64+
var projection =
65+
spec.createProjection(
66+
Path.from( BasicEntity.class)
67+
.to( BasicEntity_.other )
68+
.to( OtherEntity_.id ) );
7069
var id = projection.createQuery( session ).getSingleResult();
7170
assertNull( id );
7271
});

0 commit comments

Comments
 (0)