3
3
import com .codingapi .springboot .framework .dto .request .Filter ;
4
4
import com .codingapi .springboot .framework .dto .request .PageRequest ;
5
5
import com .codingapi .springboot .framework .dto .request .RequestFilter ;
6
- import javax .persistence .criteria .CriteriaBuilder ;
7
- import javax .persistence .criteria .Order ;
8
- import javax .persistence .criteria .Predicate ;
9
- import javax .persistence .criteria .Root ;
10
6
import org .springframework .beans .BeanUtils ;
11
7
import org .springframework .data .domain .Example ;
12
8
9
+ import javax .persistence .ManyToMany ;
10
+ import javax .persistence .ManyToOne ;
11
+ import javax .persistence .OneToMany ;
12
+ import javax .persistence .OneToOne ;
13
+ import javax .persistence .criteria .*;
13
14
import java .beans .PropertyDescriptor ;
15
+ import java .lang .reflect .Field ;
14
16
import java .util .ArrayList ;
15
17
import java .util .Date ;
16
18
import java .util .List ;
19
+ import java .util .Set ;
17
20
18
21
public class QueryRequest {
19
22
@@ -52,10 +55,22 @@ public <T> Example<T> getExample() {
52
55
53
56
54
57
private List <String > getClazzProperties () {
58
+ return getClazzProperties (clazz );
59
+ }
60
+
61
+ private List <String > getClazzProperties (Class <?> clazz ) {
55
62
List <String > properties = new ArrayList <>();
56
63
PropertyDescriptor [] descriptors = BeanUtils .getPropertyDescriptors (clazz );
57
64
for (PropertyDescriptor descriptor : descriptors ) {
58
- properties .add (descriptor .getName ());
65
+ Class <?> propertyType = descriptor .getPropertyType ();
66
+ String name = descriptor .getName ();
67
+ if (propertyType .getPackage () != null && !propertyType .getPackage ().getName ().startsWith ("java" )) {
68
+ List <String > childProperties = getClazzProperties (propertyType );
69
+ for (String child : childProperties ) {
70
+ properties .add (name + "." + child );
71
+ }
72
+ }
73
+ properties .add (name );
59
74
}
60
75
return properties ;
61
76
}
@@ -73,91 +88,113 @@ public <T> List<Order> getOrder(Root<T> root, CriteriaBuilder criteriaBuilder) {
73
88
return orderList ;
74
89
}
75
90
91
+ private Path getPathByKey (Root root , String key ) {
92
+ String [] keys = key .split ("\\ ." );
93
+ if (keys .length > 1 ) {
94
+ String lastKey = keys [keys .length -1 ];
95
+ From current = root ;
96
+ for (int i =0 ;i < keys .length -1 ;i ++) {
97
+ String item = keys [i ];
98
+ Set <Join > joins = current .getJoins ();
99
+ for (Join <?, ?> join : joins ) {
100
+ if (join .getModel ().getBindableJavaType ().getSimpleName ().equalsIgnoreCase (item )) {
101
+ current = join ;
102
+ }
103
+ }
104
+ }
105
+ return current .get (lastKey );
106
+ } else {
107
+ return root .get (key );
108
+ }
109
+ }
110
+
76
111
77
112
private <T > Predicate toPredicate (Filter filter , CriteriaBuilder criteriaBuilder , Root <T > root , List <String > properties ) {
78
113
String key = filter .getKey ();
79
114
if (filter .isAndFilters () || filter .isOrFilters () || properties .contains (key )) {
80
115
116
+ Path path = getPathByKey (root , key );
117
+
81
118
if (filter .isEqual ()) {
82
- return criteriaBuilder .equal (root . get ( key ) , filter .getValue ()[0 ]);
119
+ return criteriaBuilder .equal (path , filter .getValue ()[0 ]);
83
120
}
84
121
85
122
if (filter .isLike ()) {
86
123
String matchValue = (String ) filter .getValue ()[0 ];
87
- return criteriaBuilder .like (root . get ( key ) , "%" + matchValue + "%" );
124
+ return criteriaBuilder .like (path , "%" + matchValue + "%" );
88
125
}
89
126
90
127
if (filter .isBetween ()) {
91
128
Object value1 = filter .getValue ()[0 ];
92
129
Object value2 = filter .getValue ()[2 ];
93
130
if (value1 instanceof Integer && value2 instanceof Integer ) {
94
- return criteriaBuilder .between (root . get ( key ) , (Integer ) value1 , (Integer ) value2 );
131
+ return criteriaBuilder .between (path , (Integer ) value1 , (Integer ) value2 );
95
132
}
96
133
97
134
if (value1 instanceof Long && value2 instanceof Long ) {
98
- return criteriaBuilder .between (root . get ( key ) , (Long ) value1 , (Long ) value2 );
135
+ return criteriaBuilder .between (path , (Long ) value1 , (Long ) value2 );
99
136
}
100
137
101
138
if (value1 instanceof Date && value2 instanceof Date ) {
102
- return criteriaBuilder .between (root . get ( key ) , (Date ) value1 , (Date ) value2 );
139
+ return criteriaBuilder .between (path , (Date ) value1 , (Date ) value2 );
103
140
}
104
141
}
105
142
106
143
if (filter .isGreaterThan ()) {
107
144
Object value = filter .getValue ()[0 ];
108
145
if (value instanceof Integer ) {
109
- return criteriaBuilder .greaterThan (root . get ( key ) , (Integer ) value );
146
+ return criteriaBuilder .greaterThan (path , (Integer ) value );
110
147
}
111
148
if (value instanceof Long ) {
112
- return criteriaBuilder .greaterThan (root . get ( key ) , (Long ) value );
149
+ return criteriaBuilder .greaterThan (path , (Long ) value );
113
150
}
114
151
if (value instanceof Date ) {
115
- return criteriaBuilder .greaterThan (root . get ( key ) , (Date ) value );
152
+ return criteriaBuilder .greaterThan (path , (Date ) value );
116
153
}
117
154
}
118
155
119
156
if (filter .isGreaterThanEqual ()) {
120
157
Object value = filter .getValue ()[0 ];
121
158
if (value instanceof Integer ) {
122
- return criteriaBuilder .greaterThanOrEqualTo (root . get ( key ) , (Integer ) value );
159
+ return criteriaBuilder .greaterThanOrEqualTo (path , (Integer ) value );
123
160
}
124
161
if (value instanceof Long ) {
125
- return criteriaBuilder .greaterThanOrEqualTo (root . get ( key ) , (Long ) value );
162
+ return criteriaBuilder .greaterThanOrEqualTo (path , (Long ) value );
126
163
}
127
164
if (value instanceof Date ) {
128
- return criteriaBuilder .greaterThanOrEqualTo (root . get ( key ) , (Date ) value );
165
+ return criteriaBuilder .greaterThanOrEqualTo (path , (Date ) value );
129
166
}
130
167
}
131
168
132
169
if (filter .isLessThan ()) {
133
170
Object value = filter .getValue ()[0 ];
134
171
if (value instanceof Integer ) {
135
- return criteriaBuilder .lessThan (root . get ( key ) , (Integer ) value );
172
+ return criteriaBuilder .lessThan (path , (Integer ) value );
136
173
}
137
174
if (value instanceof Long ) {
138
- return criteriaBuilder .lessThan (root . get ( key ) , (Long ) value );
175
+ return criteriaBuilder .lessThan (path , (Long ) value );
139
176
}
140
177
if (value instanceof Date ) {
141
- return criteriaBuilder .lessThan (root . get ( key ) , (Date ) value );
178
+ return criteriaBuilder .lessThan (path , (Date ) value );
142
179
}
143
180
}
144
181
145
182
if (filter .isLessThanEqual ()) {
146
183
Object value = filter .getValue ()[0 ];
147
184
if (value instanceof Integer ) {
148
- return criteriaBuilder .lessThanOrEqualTo (root . get ( key ) , (Integer ) value );
185
+ return criteriaBuilder .lessThanOrEqualTo (path , (Integer ) value );
149
186
}
150
187
if (value instanceof Long ) {
151
- return criteriaBuilder .lessThanOrEqualTo (root . get ( key ) , (Long ) value );
188
+ return criteriaBuilder .lessThanOrEqualTo (path , (Long ) value );
152
189
}
153
190
if (value instanceof Date ) {
154
- return criteriaBuilder .lessThanOrEqualTo (root . get ( key ) , (Date ) value );
191
+ return criteriaBuilder .lessThanOrEqualTo (path , (Date ) value );
155
192
}
156
193
}
157
194
158
195
if (filter .isIn ()) {
159
196
Object [] value = filter .getValue ();
160
- CriteriaBuilder .In <Object > in = criteriaBuilder .in (root . get ( key ) );
197
+ CriteriaBuilder .In <Object > in = criteriaBuilder .in (path );
161
198
for (Object item : value ) {
162
199
in .value (item );
163
200
}
@@ -192,10 +229,33 @@ private <T> Predicate toPredicate(Filter filter, CriteriaBuilder criteriaBuilder
192
229
}
193
230
194
231
232
+ private void fetchJoins (From root , Class <?> clazz ) {
233
+ Field [] fields = clazz .getDeclaredFields ();
234
+ for (Field field : fields ) {
235
+ if (field .getAnnotation (OneToOne .class ) != null ) {
236
+ Join <?, ?> join = root .join (field .getName (), JoinType .INNER );
237
+ this .fetchJoins (join , field .getType ());
238
+ }
239
+ if (field .getAnnotation (ManyToOne .class ) != null ) {
240
+ Join <?, ?> join = root .join (field .getName (), JoinType .INNER );
241
+ this .fetchJoins (join , field .getType ());
242
+ }
243
+ if (field .getAnnotation (OneToMany .class ) != null ) {
244
+ Join <?, ?> join = root .join (field .getName (), JoinType .INNER );
245
+ this .fetchJoins (join , field .getType ());
246
+ }
247
+ if (field .getAnnotation (ManyToMany .class ) != null ) {
248
+ Join <?, ?> join = root .join (field .getName (), JoinType .INNER );
249
+ this .fetchJoins (join , field .getType ());
250
+ }
251
+ }
252
+ }
253
+
195
254
public <T > List <Predicate > getPredicate (Root <T > root , CriteriaBuilder criteriaBuilder ) {
196
255
List <Predicate > predicates = new ArrayList <>();
197
256
List <String > properties = getClazzProperties ();
198
257
RequestFilter requestFilter = request .getRequestFilter ();
258
+ this .fetchJoins (root , clazz );
199
259
for (Filter filter : requestFilter .getFilters ()) {
200
260
Predicate predicate = toPredicate (filter , criteriaBuilder , root , properties );
201
261
if (predicate != null ) {
0 commit comments