1515 */
1616package org .springframework .data .jpa .criteria ;
1717
18- import static org .assertj .core .api .Assertions .*;
18+ import static org .assertj .core .api .Assertions .assertThat ;
19+ import static org .assertj .core .api .InstanceOfAssertFactories .type ;
1920
2021import jakarta .persistence .EntityManager ;
2122import jakarta .persistence .criteria .CriteriaBuilder ;
2627import jakarta .persistence .criteria .JoinType ;
2728import jakarta .persistence .criteria .Path ;
2829import jakarta .persistence .criteria .Root ;
30+ import jakarta .persistence .criteria .Selection ;
31+
32+ import java .util .function .Function ;
2933
3034import org .junit .jupiter .api .BeforeEach ;
3135import org .junit .jupiter .api .Test ;
32-
3336import org .springframework .beans .factory .annotation .Autowired ;
3437import org .springframework .data .core .TypedPropertyPath ;
3538import org .springframework .data .jpa .domain .sample .Role ;
4043 * Integration tests for {@link Expressions}.
4144 *
4245 * @author Mark Paluch
46+ * @author Christoph Strobl
4347 */
4448@ SpringJUnitConfig (locations = "classpath:hibernate-h2-infrastructure.xml" )
4549class ExpressionsTests {
@@ -54,75 +58,58 @@ void setUp() {
5458 @ Test // GH-4085
5559 void shouldResolveTopLevelExpression () {
5660
57- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
58- CriteriaQuery <Object > query = cb .createQuery ();
59- Root <User > from = query .from (User .class );
61+ QueryExpression <User , Expression <String >> qe = expression (User .class ,
62+ from -> Expressions .get (from , User ::getFirstname ));
6063
61- Expression <String > expression = Expressions .get (from , User ::getFirstname );
62- assertThat (expression .getJavaType ()).isEqualTo (String .class );
64+ assertThat (qe .expression ().getJavaType ()).isEqualTo (String .class );
6365 }
6466
6567 @ Test // GH-4085
6668 void shouldResolveNestedLevelExpression () {
6769
68- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
69- CriteriaQuery <Object > query = cb .createQuery ();
70- Root <User > from = query .from (User .class );
71-
72- Expression <Role > expression = Expressions .get (from ,
73- TypedPropertyPath .of (User ::getManager ).thenMany (User ::getRoles ));
74- assertThat (expression .getJavaType ()).isEqualTo (Role .class );
70+ QueryExpression <User , Expression <Role >> qe = expression (User .class ,
71+ from -> Expressions .get (from , TypedPropertyPath .of (User ::getManager ).thenMany (User ::getRoles )));
72+ assertThat (qe .expression ().getJavaType ()).isEqualTo (Role .class );
7573 }
7674
7775 @ Test // GH-4085
7876 void shouldSelectExpression () {
7977
80- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
81- CriteriaQuery <Object > query = cb .createQuery ();
82- Root <User > from = query .from (User .class );
78+ QueryExpression <User , Selection <String >> path = expression (User .class ,
79+ from -> Expressions .select (from , User ::getFirstname ));
8380
84- Path <?> path = (Path <?>) Expressions .select (from , User ::getFirstname );
85-
86- assertThat (path .getJavaType ()).isEqualTo (String .class );
87- assertThat (path .getParentPath ()).isEqualTo (from );
81+ assertThat (path .expression ().getJavaType ()).isEqualTo (String .class );
82+ assertThat (path .expression ()).asInstanceOf (type (Path .class )).extracting (Path ::getParentPath ).isEqualTo (path .root ());
8883 }
8984
9085 @ Test // GH-4085
9186 void shouldSelectJoinedExpression () {
9287
93- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
94- CriteriaQuery <Object > query = cb .createQuery ();
95- Root <User > from = query .from (User .class );
88+ QueryExpression <User , Selection <String >> path = expression (User .class ,
89+ from -> Expressions .select (from , TypedPropertyPath .of (User ::getManager ).then (User ::getLastname )));
9690
97- Path <?> path = (Path <?>) Expressions .select (from , TypedPropertyPath .of (User ::getManager ).then (User ::getLastname ));
98-
99- assertThat (path .getParentPath ()).isInstanceOf (Join .class );
91+ assertThat (path .expression ()).asInstanceOf (type (Path .class )).extracting (Path ::getParentPath )
92+ .isInstanceOf (Join .class );
10093 }
10194
10295 @ Test // GH-4085
10396 void shouldJoin () {
10497
105- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
106- CriteriaQuery <Object > query = cb .createQuery ();
107- Root <User > from = query .from (User .class );
108-
109- Join <User , User > join = Expressions .join (from , User ::getManager );
98+ QueryExpression <User , Join <User , User >> join = expression (User .class ,
99+ from -> Expressions .join (from , User ::getManager ));
110100
111- assertThat (join .getJavaType ()).isEqualTo (User .class );
112- assertThat (join .getAttribute ().getName ()).isEqualTo ("manager" );
101+ assertThat (join .expression (). getJavaType ()).isEqualTo (User .class );
102+ assertThat (join .expression (). getAttribute ().getName ()).isEqualTo ("manager" );
113103 }
114104
115105 @ Test // GH-4085
116106 void shouldJoinWithType () {
117107
118- CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
119- CriteriaQuery <Object > query = cb .createQuery ();
120- Root <User > from = query .from (User .class );
121-
122- Join <User , User > join = Expressions .join (from , JoinType .LEFT , it -> it .join (User ::getManager ));
108+ QueryExpression <User , Join <User , User >> join = expression (User .class ,
109+ from -> Expressions .join (from , JoinType .LEFT , it -> it .join (User ::getManager )));
123110
124- assertThat (join .getJavaType ()).isEqualTo (User .class );
125- assertThat (join .getJoinType ()).isEqualTo (JoinType .LEFT );
111+ assertThat (join .expression (). getJavaType ()).isEqualTo (User .class );
112+ assertThat (join .expression (). getJoinType ()).isEqualTo (JoinType .LEFT );
126113 }
127114
128115 @ Test // GH-4085
@@ -150,4 +137,20 @@ void shouldFetchWithType() {
150137 assertThat (fetch .getJoinType ()).isEqualTo (JoinType .LEFT );
151138 }
152139
140+ <T , R , S extends Selection <R >> QueryExpression <T , S > expression (Class <T > type , Function <Root <T >, S > callable ) {
141+
142+ CriteriaBuilder cb = entityManager .getCriteriaBuilder ();
143+ CriteriaQuery <Object > query = cb .createQuery ();
144+ Root <T > from = query .from (type );
145+
146+ QueryExpression <T , S > qe = new QueryExpression <>(from , callable .apply (from ));
147+
148+ entityManager .createQuery (query ); // validate the query
149+ return qe ;
150+
151+ }
152+
153+ private record QueryExpression <T , S >(Root <T > root , S expression ) {
154+ }
155+
153156}
0 commit comments