diff --git a/graphql-jpa-query-boot-starter/.project b/graphql-jpa-query-boot-starter/.project
index 58102b1fd..e092c11eb 100644
--- a/graphql-jpa-query-boot-starter/.project
+++ b/graphql-jpa-query-boot-starter/.project
@@ -16,17 +16,17 @@
- org.eclipse.m2e.core.maven2Builder
+ org.springframework.ide.eclipse.core.springbuilder
- org.springframework.ide.eclipse.core.springbuilder
+ org.springframework.ide.eclipse.boot.validation.springbootbuilder
- org.springframework.ide.eclipse.boot.validation.springbootbuilder
+ org.eclipse.m2e.core.maven2Builder
diff --git a/graphql-jpa-query-example/.project b/graphql-jpa-query-example/.project
index ece02844d..5ba341ede 100644
--- a/graphql-jpa-query-example/.project
+++ b/graphql-jpa-query-example/.project
@@ -16,17 +16,17 @@
- org.eclipse.m2e.core.maven2Builder
+ org.springframework.ide.eclipse.core.springbuilder
- org.springframework.ide.eclipse.core.springbuilder
+ org.springframework.ide.eclipse.boot.validation.springbootbuilder
- org.springframework.ide.eclipse.boot.validation.springbootbuilder
+ org.eclipse.m2e.core.maven2Builder
diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaOneToManyDataFetcher.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaOneToManyDataFetcher.java
index 37d99e5af..693f1b611 100644
--- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaOneToManyDataFetcher.java
+++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaOneToManyDataFetcher.java
@@ -18,12 +18,10 @@
import java.lang.reflect.Member;
import java.lang.reflect.Method;
-import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
-import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
@@ -37,7 +35,7 @@
import graphql.language.Argument;
import graphql.language.Field;
-import graphql.language.SelectionSet;
+import graphql.language.Selection;
import graphql.schema.DataFetchingEnvironment;
/**
@@ -63,40 +61,47 @@ public Object get(DataFetchingEnvironment environment) {
Object source = environment.getSource();
Optional whereArg = extractArgument(environment, field, GraphQLJpaSchemaBuilder.QUERY_WHERE_PARAM_NAME);
- // Resolve collection query if where argument is present
- if(whereArg.isPresent()) {
-// // Create entity graph from selection
-// EntityGraph> entityGraph = buildEntityGraph(new Field("select", new SelectionSet(Arrays.asList(field))));
-//
-// try {
-// Object result = getQuery(environment, field, true)
-// .setHint("javax.persistence.fetchgraph", entityGraph)
-// .getSingleResult();
-//
-// return getAttributeValue(result, attribute);
-// } catch (NoResultException e) {
-// }
-//
-// return Collections.emptyList();
+ // Resolve collection query if where argument is present or any field in selection has orderBy argument
+ if(whereArg.isPresent() || hasSelectionAnyOrderBy(field)) {
- EntityGraph> entityGraph = buildEntityGraph(new Field("select", new SelectionSet(Arrays.asList(field))));
+ //EntityGraph> entityGraph = buildEntityGraph(new Field("select", new SelectionSet(Arrays.asList(field))));
return getQuery(environment, field, true)
+ //.setHint("javax.persistence.fetchgraph", entityGraph) // TODO: fix runtime exception
.getResultList();
-
-// .stream()
-// .map(it -> (Tuple) it)
-// .map(tuple -> tuple.get(attribute.getName()))
-// .collect(Collectors.toList());
}
// Let hibernate resolve collection query
return getAttributeValue(source, attribute);
-
- // Must do this to resolve where and orderBy on child fields
-// return getQuery(environment, field, true).getResultList();
}
+ private boolean hasSelectionAnyOrderBy(Field field) {
+
+ if(!hasSelectionSet(field)) return false;
+
+ // Loop through all of the fields being requested
+ for(Selection selection : field.getSelectionSet().getSelections()) {
+ if (selection instanceof Field) {
+ Field selectedField = (Field) selection;
+
+ // "__typename" is part of the graphql introspection spec and has to be ignored by jpa
+ if(!"__typename".equals(selectedField.getName())) {
+
+ // Optional orderBy argument
+ Optional orderBy = selectedField.getArguments().stream()
+ .filter(this::isOrderByArgument)
+ .findFirst();
+
+ if(orderBy.isPresent()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+
+ }
@SuppressWarnings( { "rawtypes", "unchecked" } )
@Override
protected TypedQuery> getQuery(DataFetchingEnvironment environment, Field field, boolean isDistinct) {
@@ -144,7 +149,7 @@ protected TypedQuery> getQuery(DataFetchingEnvironment environment, Field fiel
* @see http://stackoverflow.com/questions/7077464/how-to-get-singularattribute-mapped-value-of-a-persistent-object
*/
@SuppressWarnings("unchecked")
- public FieldType getAttributeValue(EntityType entity, SingularAttribute field) {
+ public FieldType getAttributeValue(EntityType entity, SingularAttribute field) {
try {
Member member = field.getJavaMember();
if (member instanceof Method) {
@@ -167,7 +172,7 @@ public FieldType getAttributeValue(EntityType entity, Sin
* @see http://stackoverflow.com/questions/7077464/how-to-get-singularattribute-mapped-value-of-a-persistent-object
*/
@SuppressWarnings("unchecked")
- public FieldType getAttributeValue(EntityType entity, PluralAttribute field) {
+ public FieldType getAttributeValue(EntityType entity, PluralAttribute field) {
try {
Member member = field.getJavaMember();
if (member instanceof Method) {
diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryDataFetcher.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryDataFetcher.java
index 5b94eb36a..bec37d72c 100644
--- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryDataFetcher.java
+++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryDataFetcher.java
@@ -41,52 +41,6 @@
import graphql.schema.DataFetchingEnvironmentImpl;
import graphql.schema.GraphQLObjectType;
-/*
-query Q($ids: [Long]!, $status: String!) {
- ProcessInstancesQuery (
- page:{start:1, limit: 10}
- distinct: true
- where: {
- OR: {
- processInstanceId: {
- IN: $ids
- }
- status: {
- LIKE: $status
- }
- }
- lastModified:{
- OR: {
- AND: {
- GT: "9/01/17 0:00 AM"
- LT: "10/01/17 0:00 AM"
- }
- IS_NULL: true
- }
- }
- }
- ) {
- total
- pages
- select {
- processInstanceId(orderBy:ASC)
- processDefinitionId
- status
- tasks {
- id
- assignee,
- name
- variables {
- id
- name
- type,
- value
- }
- }
- }
- }
-}
- */
/**
* JPA Query DataFetcher implementation that fetches entities with page and where criteria expressions
*
diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/QraphQLJpaBaseDataFetcher.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/QraphQLJpaBaseDataFetcher.java
index aacfd43b1..623903402 100644
--- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/QraphQLJpaBaseDataFetcher.java
+++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/QraphQLJpaBaseDataFetcher.java
@@ -45,7 +45,6 @@
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.Bindable.BindableType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute;
@@ -150,7 +149,7 @@ protected final List getFieldArguments(Field field, CriteriaQuery> q
Optional orderByArgument = selectedField.getArguments().stream()
.filter(this::isOrderByArgument)
.findFirst();
-
+
if (orderByArgument.isPresent()) {
if ("DESC".equals(((EnumValue) orderByArgument.get().getValue()).getName()))
query.orderBy(cb.desc(fieldPath));
@@ -175,24 +174,7 @@ protected final List getFieldArguments(Field field, CriteriaQuery> q
}
}
} else {
-// // If this a collection attribute then we try eagerly fetch causing eager left join
-// // Workaround fieldPath.getModel() is always null for PluralAttribute Hibernate implementation
-// if(fieldPath instanceof PluralAttributePath) {
-// PluralAttribute,?,?> attribute = ((PluralAttributePath>) fieldPath).getAttribute();
-//
-// // Foreign side is many and there are no filter arguments
-// if((attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.ONE_TO_MANY
-// || attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.MANY_TO_MANY)
-// && selectedField.getArguments().isEmpty()
-// ) {
-// // Must use query.distinct(true) for fetch left join
-// query.distinct(true);
-// // Eagerly fetch all collection elements in parent query
-// from.fetch(attribute.getName(), JoinType.LEFT);
-// } else {
-// // Do nothing
-// }
-// }
+ // Do nothing
}
}
}
@@ -303,11 +285,6 @@ protected Predicate getPredicate(CriteriaBuilder cb, Root> from, From,?> pat
}
}
- private boolean isOuterJoin(From,?> from, String name) {
- BindableType bindableType = from.get(name).getModel().getBindableType();
- return (bindableType == BindableType.PLURAL_ATTRIBUTE) ? true : false;
- }
-
@SuppressWarnings( "unchecked" )
private R getValue(Argument argument) {
return (R) argument.getValue();
@@ -416,7 +393,8 @@ private Predicate getFieldPredicate(String fieldName, CriteriaBuilder cb, From
}
- private PredicateFilter getPredicateFilter(ObjectField objectField, DataFetchingEnvironment environment, Argument argument) {
+ @SuppressWarnings("serial")
+ private PredicateFilter getPredicateFilter(ObjectField objectField, DataFetchingEnvironment environment, Argument argument) {
EnumSet options =
EnumSet.of(PredicateFilter.Criteria.valueOf(argument.getName()));
diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/StarwarsQueryExecutorTests.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/StarwarsQueryExecutorTests.java
index 50e992b71..88de67a79 100644
--- a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/StarwarsQueryExecutorTests.java
+++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/StarwarsQueryExecutorTests.java
@@ -313,6 +313,50 @@ public void queryOrderByFields() {
assertThat(result.toString()).isEqualTo(expected);
}
+ @Test
+ public void queryOrderByFieldsNested() {
+ //given:
+ String query = "query { Humans(where: {id: {EQ: \"1000\"}}) { select {name(orderBy: DESC) homePlanet friends { name(orderBy:DESC) } } } }";
+
+ String expected = "{Humans={select=["
+ + "{name=Luke Skywalker, homePlanet=Tatooine, "
+ + "friends=["
+ + "{name=R2-D2}, "
+ + "{name=Leia Organa}, "
+ + "{name=Han Solo}, "
+ + "{name=C-3PO}"
+ + "]"
+ + "}"
+ + "]}}";
+
+ //when:
+ Object result = executor.execute(query).getData();
+
+ //then:
+ assertThat(result.toString()).isEqualTo(expected);
+ }
+
+ @Test
+ public void queryOrderByDefaultId() {
+ //given:
+ String query = "query { Humans { select { id } } }";
+
+ String expected = "{Humans={select=["
+ + "{id=1000}, "
+ + "{id=1001}, "
+ + "{id=1002}, "
+ + "{id=1003}, "
+ + "{id=1004}"
+ + "]}}";
+
+ //when:
+ Object result = executor.execute(query).getData();
+
+ //then:
+ assertThat(result.toString()).isEqualTo(expected);
+ }
+
+
@Test
public void queryByCollectionOfEnumsAtRootLevel() {
//given: