@@ -69,22 +69,10 @@ public class JpaQueryBuilder<T> {
69
69
private final Class <T > entityType ;
70
70
71
71
public <R , P > CriteriaQuery <P > buildQuery (R request , SearchConfiguration <T , P , R > searchConfiguration , Sort sort ) {
72
- Assert .notNull (request , "Search request is not defined!" );
73
- Assert .notNull (searchConfiguration , "Search configuration is not defined!" );
74
- Assert .notNull (sort , "Sort is not defined!" );
75
-
76
- Class <T > rootEntity ;
77
- if (searchConfiguration .getRootEntityResolver () == null ) {
78
- rootEntity = entityType ;
79
- }
80
- else {
81
- rootEntity = searchConfiguration .getRootEntityResolver ().apply (request );
82
- }
83
-
84
- Assert .notNull (rootEntity , "Root entity returned by resolver is not defined!" );
72
+ validateArguments (request , searchConfiguration );
85
73
86
74
CriteriaBuilder criteriaBuilder = entityManager .getCriteriaBuilder ();
87
-
75
+ Class < T > rootEntity = resolveRootEntity ( request , searchConfiguration );
88
76
Class <P > resultClass = resolveResultClass (searchConfiguration , rootEntity );
89
77
90
78
Assert .isTrue (!joinFetchExists (searchConfiguration .getJoinList ()) || entityType .isAssignableFrom (resultClass ), "Join Fetch is ony possible when result class is not an projection!" );
@@ -93,7 +81,7 @@ public <R, P> CriteriaQuery<P> buildQuery(R request, SearchConfiguration<T, P, R
93
81
94
82
Root <T > root = query .from (rootEntity );
95
83
96
- applyJoinsOrFetchesToQuery (request , root , searchConfiguration .getJoinList ());
84
+ applyJoinsOrFetchesToQuery (true , request , root , searchConfiguration .getJoinList ());
97
85
98
86
List <SearchProjection <R >> searchProjectionList = searchConfiguration .getProjectionList ();
99
87
if (!resultClass .equals (entityType ) && CollectionUtils .isEmpty (searchProjectionList )) {
@@ -108,46 +96,79 @@ public <R, P> CriteriaQuery<P> buildQuery(R request, SearchConfiguration<T, P, R
108
96
109
97
query .distinct (searchConfiguration .isDistinct ());
110
98
111
- List <Predicate > requestPredicateList = resolveQueryPredicateList (request , searchConfiguration , criteriaBuilder , root , query );
112
- List <Predicate > interceptorPredicateList = resolveInterceptorPredicateList (request , searchConfiguration .getAdditionalRestrictionResolverList (), criteriaBuilder , root , query );
99
+ resolveAndApplyPredicateList (request , searchConfiguration , criteriaBuilder , root , query );
113
100
114
- applyPredicatesToQuery (criteriaBuilder , query , searchConfiguration .isAnyMatch (), requestPredicateList , interceptorPredicateList );
115
-
116
- if (sort .isSorted ()) {
101
+ if (sort != null && sort .isSorted ()) {
117
102
query .orderBy (QueryUtils .toOrders (sort , root , criteriaBuilder ));
118
103
}
119
104
120
105
return query ;
121
106
}
122
107
123
- public CriteriaQuery <Long > convertToCountQuery (CriteriaQuery <?> query ) {
124
- @ SuppressWarnings ("unchecked" )
125
- CriteriaQuery <Long > countQuery = (CriteriaQuery <Long >) query ;
108
+ public <R , P > CriteriaQuery <Long > buildCountQuery (R request , SearchConfiguration <T , P , R > searchConfiguration ) {
109
+ validateArguments (request , searchConfiguration );
126
110
127
- clearSortAndFetchesFromQuery (countQuery );
111
+ CriteriaBuilder criteriaBuilder = entityManager .getCriteriaBuilder ();
112
+ Class <T > rootEntity = resolveRootEntity (request , searchConfiguration );
113
+ CriteriaQuery <Long > query = criteriaBuilder .createQuery (Long .class );
128
114
129
- CriteriaBuilder builder = entityManager .getCriteriaBuilder ();
130
- Root <?> root = query .getRoots ().iterator ().next ();
115
+ Root <T > root = query .from (rootEntity );
116
+
117
+ applyJoinsOrFetchesToQuery (false , request , root , searchConfiguration .getJoinList ());
131
118
132
- if (countQuery .isDistinct ()) {
133
- countQuery .select (builder .countDistinct (root ));
119
+ if (searchConfiguration .isDistinct ()) {
120
+ query .select (criteriaBuilder .countDistinct (root ));
134
121
}
135
122
else {
136
- countQuery .select (builder .count (root ));
123
+ query .select (criteriaBuilder .count (root ));
137
124
}
138
125
139
- return countQuery ;
126
+ @ SuppressWarnings ("unchecked" )
127
+ CriteriaQuery <P > castedQuery = (CriteriaQuery <P >) query ;
128
+
129
+ resolveAndApplyPredicateList (request , searchConfiguration , criteriaBuilder , root , castedQuery );
130
+
131
+ return query ;
140
132
}
141
133
142
- public CriteriaQuery <Integer > convertToExistsQuery (CriteriaQuery <?> query ) {
134
+ public <R , P > CriteriaQuery <Integer > buildExistsQuery (R request , SearchConfiguration <T , P , R > searchConfiguration ) {
135
+ validateArguments (request , searchConfiguration );
136
+
137
+ CriteriaBuilder criteriaBuilder = entityManager .getCriteriaBuilder ();
138
+ Class <T > rootEntity = resolveRootEntity (request , searchConfiguration );
139
+ CriteriaQuery <Integer > query = criteriaBuilder .createQuery (Integer .class );
140
+
141
+ Root <T > root = query .from (rootEntity );
142
+
143
+ applyJoinsOrFetchesToQuery (false , request , root , searchConfiguration .getJoinList ());
144
+
145
+ query .select (entityManager .getCriteriaBuilder ().literal (1 ));
146
+
143
147
@ SuppressWarnings ("unchecked" )
144
- CriteriaQuery <Integer > existsQuery = (CriteriaQuery <Integer >) query ;
148
+ CriteriaQuery <P > castedQuery = (CriteriaQuery <P >) query ;
149
+
150
+ resolveAndApplyPredicateList (request , searchConfiguration , criteriaBuilder , root , castedQuery );
151
+
152
+ return query ;
153
+ }
145
154
146
- clearSortAndFetchesFromQuery (existsQuery );
155
+ private <R , P > void validateArguments (R request , SearchConfiguration <T , P , R > searchConfiguration ) {
156
+ Assert .notNull (request , "Search request is not defined!" );
157
+ Assert .notNull (searchConfiguration , "Search configuration is not defined!" );
158
+ }
159
+
160
+ private <R , P > Class <T > resolveRootEntity (R request , SearchConfiguration <T , P , R > searchConfiguration ) {
161
+ Class <T > rootEntity ;
162
+ if (searchConfiguration .getRootEntityResolver () == null ) {
163
+ rootEntity = entityType ;
164
+ }
165
+ else {
166
+ rootEntity = searchConfiguration .getRootEntityResolver ().apply (request );
167
+ }
147
168
148
- existsQuery . select ( entityManager . getCriteriaBuilder (). literal ( 1 ) );
169
+ Assert . notNull ( rootEntity , "Root entity returned by resolver is not defined!" );
149
170
150
- return existsQuery ;
171
+ return rootEntity ;
151
172
}
152
173
153
174
// TODO try to use result set mapper, jpa projections require constructors with all parameters
@@ -156,14 +177,14 @@ private <R, P> Class<P> resolveResultClass(SearchConfiguration<T, P, R> searchCo
156
177
return searchConfiguration .getResultClass () == null ? (Class <P >) rootEntity : searchConfiguration .getResultClass ();
157
178
}
158
179
159
- private <R > void applyJoinsOrFetchesToQuery (R request , Root <?> root , List <SearchJoin <R >> joinList ) {
180
+ private <R > void applyJoinsOrFetchesToQuery (boolean applyFetch , R request , Root <?> root , List <SearchJoin <R >> joinList ) {
160
181
if (CollectionUtils .isEmpty (joinList )) {
161
182
return ;
162
183
}
163
184
164
185
joinList .stream ()
165
186
.filter (join -> shouldApplyJoinOrFetch (join , request ))
166
- .forEach (searchJoin -> applyJoinOrJoinFetch (root , searchJoin ));
187
+ .forEach (searchJoin -> applyJoinOrJoinFetch (root , searchJoin , applyFetch ));
167
188
}
168
189
169
190
private <R > List <Selection <?>> resolveQueryProjectionList (Root <?> root , List <SearchProjection <R >> projectionList , R request ) {
@@ -181,11 +202,11 @@ private <R> boolean shouldApplyJoinOrFetch(SearchJoin<R> join, R request) {
181
202
return join .getCondition () == null || join .getCondition ().test (request );
182
203
}
183
204
184
- private void applyJoinOrJoinFetch (Root <?> root , SearchJoin <?> searchJoin ) {
205
+ private void applyJoinOrJoinFetch (Root <?> root , SearchJoin <?> searchJoin , boolean applyFetch ) {
185
206
JoinType joinType = searchJoin .getJoinType () == null ? JoinType .INNER : searchJoin .getJoinType ();
186
207
187
208
String [] pathList = PathResolvingUtil .convertToPathList (searchJoin .getPath ());
188
- if (searchJoin .isFetch ()) {
209
+ if (applyFetch && searchJoin .isFetch ()) {
189
210
Fetch <?, ?> fetch = null ;
190
211
for (String path : pathList ) {
191
212
fetch = fetch == null ? root .fetch (path , joinType ) : fetch .fetch (path , joinType );
@@ -207,6 +228,13 @@ private <R> boolean shouldApplyProjection(SearchProjection<R> projection, R requ
207
228
return projection .getCondition () == null || projection .getCondition ().test (request );
208
229
}
209
230
231
+ private <P , R > void resolveAndApplyPredicateList (R request , SearchConfiguration <T , P , R > searchConfiguration , CriteriaBuilder criteriaBuilder , Root <T > root , CriteriaQuery <P > query ) {
232
+ List <Predicate > requestPredicateList = resolveQueryPredicateList (request , searchConfiguration , criteriaBuilder , root , query );
233
+ List <Predicate > interceptorPredicateList = resolveInterceptorPredicateList (request , searchConfiguration .getAdditionalRestrictionResolverList (), criteriaBuilder , root , query );
234
+
235
+ applyPredicatesToQuery (criteriaBuilder , query , searchConfiguration .isAnyMatch (), requestPredicateList , interceptorPredicateList );
236
+ }
237
+
210
238
private <P , R > List <Predicate > resolveQueryPredicateList (R request , SearchConfiguration <T , P , R > searchConfiguration , CriteriaBuilder criteriaBuilder , Root <?> root , CriteriaQuery <?> query ) {
211
239
Set <Restriction > restrictionList = new SearchDataParser (root .getModel (), request , SearchDataParserConfiguration .fromSearchConfiguration (searchConfiguration )).resolveRestrictionList ();
212
240
@@ -375,10 +403,4 @@ private SearchDataParserConfiguration searchDataParserConfiguration(SearchProper
375
403
.resolvePropertyMappingUsingPrefix (resolvePropertyMappingUsingPrefix )
376
404
.build ();
377
405
}
378
-
379
- private void clearSortAndFetchesFromQuery (CriteriaQuery <?> query ) {
380
- query .orderBy (Collections .emptyList ());
381
-
382
- query .getRoots ().forEach (root -> root .getFetches ().clear ());
383
- }
384
406
}
0 commit comments