Skip to content

Commit 896180a

Browse files
author
talhadilber
committed
README file updated
1 parent d299b59 commit 896180a

File tree

1 file changed

+316
-78
lines changed

1 file changed

+316
-78
lines changed

README.md

Lines changed: 316 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,317 @@
1-
# JPA - EXTENSION
2-
3-
This project look like QueryDsl but main purpuse is query creation with simple DTO (Pojo) objects. So we can simply
4-
ingrate with frontend application filters or somethings. Received query converted to Jpa Specification object and this
5-
Specification<Entity> executed on JpaSpecificationExecutor<Entity> repository.
6-
7-
```java
8-
9-
// Entity
10-
@Entity
11-
@Table(name = "customer")
12-
public class Customer implements Serializable {
13-
14-
private static final long serialVersionUID = 1L;
15-
16-
@Id
17-
@GeneratedValue(strategy = GenerationType.IDENTITY)
18-
private Long id;
19-
20-
@Column(name = "name")
21-
private String name;
22-
23-
@Column(name = "age")
24-
private Integer age;
25-
26-
@Column(name = "birthdate")
27-
private Instant birthdate;
28-
29-
@ManyToOne
30-
private User user;
31-
32-
// getter - setters
33-
}
34-
35-
// Repository Creation
36-
@Repository
37-
public interface CustomerRepository extends JpaExtendedRepository<Customer, Long> {
38-
}
39-
40-
// Usage
41-
// SELECT * FROM customer WHERE age >= 18
42-
customerRepository.findAllWithCriteria(Arrays.asList(Criteria.of("age", CriteriaType.GREATER_THAN_OR_EQUAL, 18)));
43-
44-
// Default AND operation apply on list of all criterias.
45-
// SELECT * FROM customer WHERE age >= 18 AND id < 10
46-
customerRepository.findAllWithCriteria(Arrays.asList(
47-
Criteria.of("age", CriteriaType.GREATER_THAN_OR_EQUAL, 18),
48-
Criteria.of("id", CriteriaType.LESS_THAN, 10)
49-
));
50-
51-
// OR Usage
52-
// SELECT * FROM customer WHERE age >= 18 OR id < 10
53-
customerRepository.findAllWithCriteria(Arrays.asList(
54-
Criteria.of("age", CriteriaType.GREATER_THAN_OR_EQUAL, 18),
55-
Criteria.of("", CriteriaType.OR),
56-
Criteria.of("id", CriteriaType.LESS_THAN, 10)
57-
));
58-
59-
// Joinning Usage
60-
// SELECT c.* FROM customer c INNER JOIN user u ON c.user_id=u.id WHERE u.surname LIKE '%son%'
61-
customerRepository.findAllWithCriteria(Arrays.asList(Criteria.of("user.surname", CriteriaType.CONTAIN, "son")));
62-
63-
// SELECT c.* FROM customer c LEFT JOIN user u ON c.user_id=u.id WHERE u.surname LIKE '%son%'
64-
customerRepository.findAllWithCriteria(Arrays.asList(Criteria.of("user<surname", CriteriaType.CONTAIN, "son")));
65-
66-
// SELECT c.* FROM customer c RIGHT JOIN user u ON c.user_id=u.id WHERE u.surname LIKE '%son%'
67-
customerRepository.findAllWithCriteria(Arrays.asList(Criteria.of("user>surname", CriteriaType.CONTAIN, "son")));
68-
69-
70-
// Powerfull Usage
71-
// SELECT c.* FROM customer c INNER JOIN user u ON c.user_id=u.id WHERE (u.surname LIKE '%son%' AND c.age >= 18) OR (u.name LIKE '%ander%' AND c.id < 10)
72-
customerRepository.findAllWithCriteria(Arrays.asList(
73-
Criteria.of("user.surname", CriteriaType.CONTAIN, "son"),
74-
Criteria.of("age", CriteriaType.GREATER_THAN_OR_EQUAL, 18),
75-
Criteria.of("", CriteriaType.OR),
76-
Criteria.of("user.name", CriteriaType.CONTAIN, "ander"),
77-
Criteria.of("id", CriteriaType.LESS_THAN, 10)
78-
));
1+
# Spring Jpa Dynamic Query (JDQ)
2+
3+
This project is designed to overcome the sluggishness of Spring Data JPA's query creation and the need to write separate
4+
code for each query. At its core, it simplifies the Criteria API introduced in Jpa 2, enabling programmatic or dynamic
5+
runtime query creation.
6+
7+
The query creation capabilities include 9 different field operators, AND-OR conjunctions, SCOPE support, and single or
8+
multi JOIN features. The SELECT, DISTINCT, ORDER BY clauses in the query are also supported with Joined Column. In
9+
addition, all query results can be returned as both List<?> and Page<?>. After SELECT clause, PROJECTION support is also
10+
available. This PROJECTION works with ignore missing fields rules for more flexibility.
11+
12+
You don't need to write any lines of code to create these queries, all operations including all JOIN operations are done
13+
dynamically at runtime. It is sufficient to create just one Repository interface. The objects required to call the
14+
methods related to dynamic query in the interface can be taken from within the program or from outside the program (like
15+
DTO) as Serializable. Since all query creation and database query operations are done with Criteria Api during these
16+
operations, it is as secure as Spring Data JPA, and works as fast and effectively as Spring Data JPA.
17+
18+
## Introduction
19+
20+
**This is the base Models for Jpa Dynamic Query.**
21+
22+
```java
23+
public enum CriteriaOperator {
24+
// String Operators
25+
CONTAIN, DOES_NOT_CONTAIN, END_WITH, START_WITH,
26+
// Null Check Operator
27+
SPECIFIED,
28+
// String and Comparable Operators
29+
EQUAL, NOT_EQUAL,
30+
// Comparable Operators
31+
GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL,
32+
// OR Operator
33+
OR,
34+
// SCOPE Operator
35+
PARENTHES
36+
}
37+
38+
39+
@Getter
40+
@Setter
41+
public class Criteria implements Serializable {
42+
protected String key;
43+
protected CriteriaOperator operation;
44+
protected List<Object> values;
45+
}
46+
47+
@Getter
48+
@Setter
49+
public class DynamicQuery implements Serializable {
50+
protected boolean distinct = false;
51+
protected Integer pageSize = null;
52+
protected Integer pageNumber = null;
53+
protected List<Pair<String, String>> select = new ArrayList<>();
54+
protected List<Criteria> where = new CriteriaList();
55+
protected List<Pair<String, Order>> orderBy = new ArrayList<>();
56+
}
57+
```
58+
59+
**This is the base Methods for JpaDynamicQueryRepository.**
60+
61+
```java
62+
63+
@NoRepositoryBean
64+
public interface JpaDynamicQueryRepository<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
65+
// List Entity with WHERE Clause (JOIN supported)
66+
List<T> findAll(List<Criteria> criteriaList);
67+
68+
// List Entity with WHERE Clause (JOIN supported) and Pageable
69+
Page<T> findAll(List<Criteria> criteriaList, Pageable pageable);
70+
71+
// List Entity with SELECT, DISTINCT, WHERE, ORDER BY Clause (JOIN supported) Page Supported
72+
List<T> findAll(DynamicQuery dynamicQuery);
73+
74+
// List Entity with SELECT, DISTINCT, WHERE, ORDER BY Clause (JOIN supported) Page Supported
75+
Page<T> findAllAsPage(DynamicQuery dynamicQuery);
76+
77+
// List Entity with SELECT, DISTINCT, WHERE, ORDER BY Clause (JOIN supported) Page Supported With Projection
78+
<ResultType> List<ResultType> findAll(DynamicQuery dynamicQuery, Class<ResultType> resultTypeClass);
79+
80+
// List Entity with SELECT, DISTINCT, WHERE, ORDER BY Clause (JOIN supported) Page Supported With Projection
81+
<ResultType> Page<ResultType> findAllAsPage(DynamicQuery dynamicQuery, Class<ResultType> resultTypeClass);
82+
}
83+
```
84+
85+
## Writing the Code
86+
87+
You can find the sample code from: https://github.com/tdilber/spring-jpa-dynamic-query-presentation-demo
88+
89+
### Setting up the project with Maven
90+
91+
```maven
92+
<dependency>
93+
<groupId>io.github.tdilber</groupId>
94+
<artifactId>spring-jpa-dynamic-query</artifactId>
95+
<version>0.3.1</version>
96+
</dependency>
97+
```
98+
99+
### Enable Annotation
100+
101+
Add the `@EnableJpaDynamicQuery` annotation to the main class of your project. This annotation is used to enable the
102+
dynamic query feature.
103+
104+
```java
105+
106+
@EnableJpaDynamicQuery
107+
@SpringBootApplication
108+
public class SpringJpaDynamicQueryDemoApplication {
109+
public static void main(String[] args) {
110+
SpringApplication.run(SpringJpaDynamicQueryDemoApplication.class, args);
111+
}
112+
}
113+
114+
```
115+
116+
### Create a Repository
117+
118+
**Create a Repository for Existing Entity.**
119+
120+
```java
121+
public interface AdminUserRepository extends JpaDynamicQueryRepository<AdminUser, Long> {
122+
123+
}
124+
```
125+
126+
### Operator Examples
127+
128+
#### EQUAL Operator
129+
130+
```java
131+
userRepository.findAll(CriteriaList.of(Criteria.of("status", CriteriaOperator.EQUAL, User.Status.ACTIVE)));
132+
```
133+
134+
#### NOT_EQUAL Operator
135+
136+
```java
137+
customerRepository.findAll(CriteriaList.of(Criteria.of("age", CriteriaOperator.NOT_EQUAL, 24)));
138+
```
139+
140+
#### GREATER_THAN Operator
141+
142+
```java
143+
customerRepository.findAll(CriteriaList.of(Criteria.of("age", CriteriaOperator.GREATER_THAN, 24)));
144+
```
145+
146+
#### GREATER_THAN_OR_EQUAL Operator
147+
148+
```java
149+
customerRepository.findAll(CriteriaList.of(Criteria.of("age", CriteriaOperator.GREATER_THAN_OR_EQUAL, 24)));
150+
```
151+
152+
#### LESS_THAN Operator
153+
154+
```java
155+
customerRepository.findAll(CriteriaList.of(Criteria.of("age", CriteriaOperator.LESS_THAN, 24)));
156+
```
157+
158+
#### LESS_THAN_OR_EQUAL Operator
159+
160+
```java
161+
customerRepository.findAll(CriteriaList.of(Criteria.of("age", CriteriaOperator.LESS_THAN_OR_EQUAL, 24)));
162+
```
163+
164+
#### CONTAIN Operator
165+
166+
```java
167+
customerRepository.findAll(CriteriaList.of(Criteria.of("name", CriteriaOperator.CONTAIN, "Customer")));
168+
```
169+
170+
#### DOES_NOT_CONTAIN Operator
171+
172+
```java
173+
customerRepository.findAll(CriteriaList.of(Criteria.of("name", CriteriaOperator.DOES_NOT_CONTAIN, "5")));
174+
```
175+
176+
#### START_WITH Operator
177+
178+
```java
179+
customerRepository.findAll(CriteriaList.of(Criteria.of("name", CriteriaOperator.START_WITH, "Customer")));
180+
```
181+
182+
#### END_WITH Operator
183+
184+
```java
185+
customerRepository.findAll(CriteriaList.of(Criteria.of("name", CriteriaOperator.END_WITH, " 7")));
186+
```
187+
188+
#### SPECIFIED Operator
189+
190+
```java
191+
customerRepository.findAll(CriteriaList.of(Criteria.of("name", CriteriaOperator.SPECIFIED, true)));
192+
```
193+
194+
### AND-OR Operator Examples
195+
196+
Sequentially, all criteria are evaluated with the AND operator. If you want to evaluate the criteria with the OR
197+
operator, you can use the `Criteria.OR()` method.
198+
199+
```java
200+
customerRepository.findAll(CriteriaList.of(
201+
Criteria.of("name", CriteriaOperator.EQUAL, "Customer 1"),
202+
Criteria.
203+
204+
OR(),
205+
Criteria.
206+
207+
of("name",CriteriaOperator.EQUAL, "Customer 2")
208+
));
209+
```
210+
211+
### SCOPE Operator Examples
212+
213+
```java
214+
var criteriaList = CriteriaList.of(
215+
Criteria.of("", CriteriaOperator.PARENTHES,
216+
CriteriaList.of(Criteria.of(Course.Fields.id, CriteriaOperator.EQUAL, 1),
217+
Criteria.OR(),
218+
Criteria.of(Course.Fields.id, CriteriaOperator.EQUAL, 2))),
219+
Criteria.of("", CriteriaOperator.PARENTHES,
220+
CriteriaList.of(Criteria.of(Course.Fields.id, CriteriaOperator.EQUAL, 2),
221+
Criteria.OR(),
222+
Criteria.of(Course.Fields.id, CriteriaOperator.EQUAL, 3)))
223+
);
224+
List<Course> courseList = courseRepository.findAll(criteriaList);
225+
```
226+
227+
### Pagination Examples
228+
229+
```java
230+
DynamicQuery dynamicQuery = new DynamicQuery();
231+
dynamicQuery.
232+
233+
setWhere(CriteriaList.of(Criteria.of(Course.Fields.id, CriteriaOperator.GREATER_THAN, 3)));
234+
dynamicQuery.
235+
236+
setPageSize(2);
237+
dynamicQuery.
238+
239+
setPageNumber(1);
240+
241+
Page<Course> result = courseRepository.findAllAsPage(dynamicQuery);
79242
```
243+
244+
### Projection Examples
245+
246+
```java
247+
DynamicQuery dynamicQuery = new DynamicQuery();
248+
dynamicQuery.
249+
250+
getSelect().
251+
252+
add(Pair.of("id", "adminId"));
253+
dynamicQuery.
254+
255+
getSelect().
256+
257+
add(Pair.of("username", "adminUsername"));
258+
dynamicQuery.
259+
260+
getSelect().
261+
262+
add(Pair.of("roles.id", "roleId"));
263+
dynamicQuery.
264+
265+
getSelect().
266+
267+
add(Pair.of("roles.name", "roleName"));
268+
dynamicQuery.
269+
270+
getSelect().
271+
272+
add(Pair.of("roles.roleAuthorizations.authorization.id", "authorizationId"));
273+
dynamicQuery.
274+
275+
getSelect().
276+
277+
add(Pair.of("roles.roleAuthorizations.authorization.name", "authorizationName"));
278+
dynamicQuery.
279+
280+
getSelect().
281+
282+
add(Pair.of("roles.roleAuthorizations.authorization.menuIcon", "menuIcon"));
283+
var criteriaList = CriteriaList.of(Criteria.of("roles.roleAuthorizations.authorization.menuIcon", CriteriaOperator.START_WITH, "icon"));
284+
dynamicQuery.
285+
286+
getWhere().
287+
288+
addAll(criteriaList);
289+
290+
List<AuthorizationSummary> result2 = adminUserRepository.findAll(dynamicQuery, AuthorizationSummary.class);
291+
```
292+
293+
### Query Builder Examples
294+
295+
```java
296+
Page<AuthorizationSummary> result = adminUserRepository.queryBuilder()
297+
.select(Select("id", "adminId"),
298+
Select("username", "adminUsername"),
299+
Select("roles.id", "roleId"),
300+
Select("roles.name", "roleName"),
301+
Select("roles.roleAuthorizations.authorization.id", "authorizationId"),
302+
Select("roles.roleAuthorizations.authorization.name", "authorizationName"),
303+
Select("roles.roleAuthorizations.authorization.menuIcon", "menuIcon"))
304+
.distinct(false)
305+
.where(Field("roles.roleAuthorizations.authorization.menuIcon").startWith("icon"), Parantesis(Field("id").eq(3), OR, Field("roles.id").eq(4), OR, Field("id").eq(5)), Parantesis(Field("id").eq(5), OR, Field("id").eq(4), OR, Field("roles.id").eq(3)))
306+
.orderBy(OrderBy("roles.id", Order.DESC))
307+
.page(1, 2)
308+
.getResultAsPage(AuthorizationSummary.class);
309+
```
310+
311+
## Conclusion
312+
313+
This introduction not enough pls visit https://github.com/tdilber/spring-jpa-dynamic-query-presentation-demo address for
314+
more specific examples and details.
315+
316+
317+

0 commit comments

Comments
 (0)