Skip to content

Commit b296d8a

Browse files
authored
feat: add where relation attributes criteria expressions (#96)
* fix: add missing data.sql in example * feat: add where relation attribute filter criteria expressions * fix: polish merge example query name and description * fix: Hibernate error using query specified join fetching * fix: enable variable parameter bindings * fix: polish relation criteria expression type name * fix: reuse joins for relation criteria expression argument predicates * fix: support AND/OR in relation attribute filters * fix: use hint hibernate.query.passDistinctThrough=false * chore: remove .project from git * chore: polish and refactor internal DataFetcher code * fix: clear entityManager session cache for every request * chore: add Hibernate properties to examples * chore: polish GraphQLJpaQueryDataFetcher internals * Update README.md * fix: reuse join for singular many-to-one attributes * fix: use fetch=LAZY for all relations in example entity models
1 parent 2933500 commit b296d8a

File tree

25 files changed

+971
-347
lines changed

25 files changed

+971
-347
lines changed

.project

Lines changed: 0 additions & 17 deletions
This file was deleted.

README.md

Lines changed: 195 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ Will return:
150150

151151
Query Wrapper with Where Criteria Expressions
152152
-------------------------------------
153-
This library supports flexible type safe criteria expressions with user-friendly SQL query syntax semantics using `where` arguments and `select` field to specify the entity graph query with entiy attribute names as a combination of logical expressions like OR, AND, EQ, NE, GT, GE, LT, LR, IN, NIN, IS_NULL, NOT_NULL, BETWEEN, NOT_BETWEEN.
153+
This library supports flexible type safe criteria expressions with user-friendly SQL query syntax semantics using `where` arguments and `select` field to specify the entity graph query with entiy attribute names as a combination of logical expressions like EQ, NE, GT, GE, LT, LR, IN, NIN, IS_NULL, NOT_NULL, BETWEEN, NOT_BETWEEN. You can use logical AND/OR combinations in SQL criteria expressions to specify complex criterias to fetch your data from SQL database. If you omit, where argument, all entities will be returned.
154154

155155
For Example:
156156

@@ -173,7 +173,200 @@ Will return:
173173
}
174174
}
175175

176-
You can use familiar SQL criteria expressions to specify complex criterias to fetch your data from SQL database. If you omit, where argument, all entities will be returned.
176+
Relation Attributes in Where Criteria Expressions:
177+
----------------------------
178+
It is also possible to specify complex filters using many-to-one and one-to-many entity attributes in where criteria expressions with variable parameter bindings, i.e.
179+
180+
Given the following query with many-to-one relation with variables `{"authorId": 1 }` :
181+
182+
```
183+
query($authorId: Long) {
184+
Books(where: {
185+
author: {id: {EQ: $authorId}}
186+
}) {
187+
select {
188+
id
189+
title
190+
genre
191+
author {
192+
id
193+
name
194+
}
195+
}
196+
}
197+
}
198+
```
199+
200+
will result in
201+
202+
```
203+
{
204+
"data": {
205+
"Books": {
206+
"select": [
207+
{
208+
"id": 2,
209+
"title": "War and Peace",
210+
"genre": "NOVEL",
211+
"author": {
212+
"id": 1,
213+
"name": "Leo Tolstoy"
214+
}
215+
},
216+
{
217+
"id": 3,
218+
"title": "Anna Karenina",
219+
"genre": "NOVEL",
220+
"author": {
221+
"id": 1,
222+
"name": "Leo Tolstoy"
223+
}
224+
}
225+
]
226+
}
227+
}
228+
}
229+
```
230+
231+
And given the following query with one-to-many relation:
232+
233+
```
234+
query {
235+
Authors(where: {
236+
books: {genre: {IN: NOVEL}}
237+
}) {
238+
select {
239+
id
240+
name
241+
books {
242+
id
243+
title
244+
genre
245+
}
246+
}
247+
}
248+
}
249+
```
250+
251+
will result in
252+
253+
```
254+
{
255+
"data": {
256+
"Authors": {
257+
"select": [
258+
{
259+
"id": 1,
260+
"name": "Leo Tolstoy",
261+
"books": [
262+
{
263+
"id": 2,
264+
"title": "War and Peace",
265+
"genre": "NOVEL"
266+
},
267+
{
268+
"id": 3,
269+
"title": "Anna Karenina",
270+
"genre": "NOVEL"
271+
}
272+
]
273+
}
274+
]
275+
}
276+
}
277+
}
278+
```
279+
280+
It is possible to use compound criterias in where search expressions given:
281+
282+
```
283+
query {
284+
Authors(where: {
285+
books: {
286+
genre: {IN: NOVEL}
287+
title: {LIKE: "War"}
288+
}
289+
}) {
290+
select {
291+
id
292+
name
293+
books {
294+
id
295+
title
296+
genre
297+
}
298+
}
299+
}
300+
}
301+
```
302+
303+
Will return filtered inner collection result:
304+
305+
```
306+
{
307+
"data": {
308+
"Authors": {
309+
"select": [
310+
{
311+
"id": 1,
312+
"name": "Leo Tolstoy",
313+
"books": [
314+
{
315+
"id": 2,
316+
"title": "War and Peace",
317+
"genre": "NOVEL"
318+
}
319+
]
320+
}
321+
]
322+
}
323+
}
324+
}
325+
```
326+
327+
It is also possible to filter inner collections as follows:
328+
329+
```
330+
query {
331+
Authors(where: {
332+
books: {genre: {IN: NOVEL}}
333+
}) {
334+
select {
335+
id
336+
name
337+
books(where: {title: {LIKE: "War"}}) {
338+
id
339+
title
340+
genre
341+
}
342+
}
343+
}
344+
}
345+
```
346+
347+
will result in
348+
349+
```
350+
{
351+
"data": {
352+
"Authors": {
353+
"select": [
354+
{
355+
"id": 1,
356+
"name": "Leo Tolstoy",
357+
"books": [
358+
{
359+
"id": 2,
360+
"title": "War and Peace",
361+
"genre": "NOVEL"
362+
}
363+
]
364+
}
365+
]
366+
}
367+
}
368+
}
369+
```
177370

178371
Collection Filtering
179372
--------------------

graphql-jpa-query-boot-starter/.project

Lines changed: 0 additions & 56 deletions
This file was deleted.

graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/books/Author.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Collection;
2020

2121
import javax.persistence.Entity;
22+
import javax.persistence.FetchType;
2223
import javax.persistence.Id;
2324
import javax.persistence.OneToMany;
2425

@@ -32,6 +33,6 @@ public class Author {
3233

3334
String name;
3435

35-
@OneToMany(mappedBy="author")
36+
@OneToMany(mappedBy="author", fetch=FetchType.LAZY)
3637
Collection<Book> books;
3738
}

graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/books/Book.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import javax.persistence.Entity;
2020
import javax.persistence.EnumType;
2121
import javax.persistence.Enumerated;
22+
import javax.persistence.FetchType;
2223
import javax.persistence.Id;
2324
import javax.persistence.ManyToOne;
2425

@@ -32,7 +33,7 @@ public class Book {
3233

3334
String title;
3435

35-
@ManyToOne
36+
@ManyToOne(fetch=FetchType.LAZY)
3637
Author author;
3738

3839
@Enumerated(EnumType.STRING)

graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/starwars/Character.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import javax.persistence.Entity;
2323
import javax.persistence.EnumType;
2424
import javax.persistence.Enumerated;
25+
import javax.persistence.FetchType;
2526
import javax.persistence.Id;
2627
import javax.persistence.JoinColumn;
2728
import javax.persistence.JoinTable;
2829
import javax.persistence.ManyToMany;
2930
import javax.persistence.OrderBy;
3031

3132
import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription;
33+
3234
import lombok.EqualsAndHashCode;
3335
import lombok.Getter;
3436
import lombok.Setter;
@@ -50,14 +52,14 @@ public abstract class Character {
5052
String name;
5153

5254
@GraphQLDescription("Who are the known friends to this character")
53-
@ManyToMany
54-
@JoinTable(name="character_friends",
55+
@ManyToMany(fetch = FetchType.LAZY)
56+
@JoinTable(name="character_friends",
5557
joinColumns=@JoinColumn(name="source_id", referencedColumnName="id"),
5658
inverseJoinColumns=@JoinColumn(name="friend_id", referencedColumnName="id"))
5759
Set<Character> friends;
5860

5961
@GraphQLDescription("What Star Wars episodes does this character appear in")
60-
@ElementCollection(targetClass = Episode.class)
62+
@ElementCollection(targetClass = Episode.class, fetch = FetchType.LAZY)
6163
@Enumerated(EnumType.ORDINAL)
6264
@OrderBy
6365
Set<Episode> appearsIn;

graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/starwars/CodeList.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
package com.introproventures.graphql.jpa.query.example.starwars;
1818

1919
import javax.persistence.Entity;
20+
import javax.persistence.FetchType;
2021
import javax.persistence.Id;
2122
import javax.persistence.JoinColumn;
2223
import javax.persistence.ManyToOne;
2324

2425
import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription;
26+
2527
import lombok.Data;
2628

2729
@Entity
@@ -39,7 +41,7 @@ public class CodeList {
3941
boolean active;
4042
String description;
4143

42-
@ManyToOne
44+
@ManyToOne(fetch = FetchType.LAZY)
4345
@JoinColumn(name = "parent_id")
4446
CodeList parent;
4547

graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/starwars/Human.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class Human extends Character {
3535
@JoinColumn(name = "favorite_droid_id")
3636
Droid favoriteDroid;
3737

38-
@ManyToOne
38+
@ManyToOne(fetch = FetchType.LAZY)
3939
@JoinColumn(name = "gender_code_id")
4040
CodeList gender;
4141

0 commit comments

Comments
 (0)