Skip to content

Commit 38bfb17

Browse files
authored
fix(GH-220): Cannot nest multiple queries on the same table (#222)
* fix: plural attributes double wrapping in list type * fix: Applied consistent behaviors for JOIN and EXISTS criteria expressions * fix: add tests * feat: Added isShouldClearContext configuration to invoke clear() for EM * fixme: Added failing tests to fix some time later * chore: find and replace '\n' with '' * fix: remove wrong hint * fix: Added test for many-2- many query using both sides of the relationship * Revert "feat: Added isShouldClearContext configuration to invoke clear() for EM" This reverts commit c5ac022. * fix: Corrected StarwarsQueryExecutor failing unit tests
1 parent 963826f commit 38bfb17

File tree

7 files changed

+628
-133
lines changed

7 files changed

+628
-133
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import javax.persistence.OrderBy;
3131

3232
import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription;
33+
3334
import lombok.EqualsAndHashCode;
3435
import lombok.Getter;
3536
import lombok.Setter;
@@ -40,7 +41,7 @@
4041
@Getter
4142
@Setter
4243
@ToString
43-
@EqualsAndHashCode(exclude={"appearsIn","friends"}) // Fixes NPE in Hibernate when initializing loaded collections #1
44+
@EqualsAndHashCode(exclude={"appearsIn","friends", "friendsOf"}) // Fixes NPE in Hibernate when initializing loaded collections #1
4445
public abstract class Character {
4546

4647
@Id
@@ -58,6 +59,10 @@ public abstract class Character {
5859
@OrderBy("name ASC")
5960
Set<Character> friends;
6061

62+
@ManyToMany(fetch=FetchType.LAZY, mappedBy = "friends")
63+
@OrderBy("name ASC")
64+
Set<Character> friendsOf;
65+
6166
@GraphQLDescription("What Star Wars episodes does this character appear in")
6267
@ElementCollection(targetClass = Episode.class, fetch=FetchType.LAZY)
6368
@Enumerated(EnumType.ORDINAL)

graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private GraphQLInputObjectType computeSubqueryInputType(ManagedType<?> managedTy
332332
.build()
333333
)
334334
.fields(managedType.getAttributes().stream()
335-
.filter(this::isValidAssociation)
335+
.filter(Attribute::isAssociation)
336336
.filter(this::isNotIgnored)
337337
.filter(this::isNotIgnoredFilter)
338338
.map(this::getWhereInputRelationField)
@@ -404,7 +404,7 @@ private GraphQLInputObjectType computeWhereInputType(ManagedType<?> managedType)
404404
.collect(Collectors.toList())
405405
)
406406
.fields(managedType.getAttributes().stream()
407-
.filter(this::isValidAssociation)
407+
.filter(Attribute::isAssociation)
408408
.filter(this::isNotIgnored)
409409
.filter(this::isNotIgnoredFilter)
410410
.map(this::getWhereInputRelationField)
@@ -853,7 +853,9 @@ else if (isElementCollection(attribute)) {
853853
Type foreignType = ((PluralAttribute) attribute).getElementType();
854854

855855
if(foreignType.getPersistenceType() == Type.PersistenceType.BASIC) {
856-
return new GraphQLList(getGraphQLTypeFromJavaType(foreignType.getJavaType()));
856+
GraphQLType graphQLType = getGraphQLTypeFromJavaType(foreignType.getJavaType());
857+
858+
return input ? graphQLType : new GraphQLList(graphQLType);
857859
}
858860
}
859861

@@ -897,11 +899,6 @@ protected final boolean isValidInput(Attribute<?,?> attribute) {
897899
attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED;
898900
}
899901

900-
protected final boolean isValidAssociation(Attribute<?,?> attribute) {
901-
return isOneToMany(attribute) || isToOne(attribute);
902-
}
903-
904-
905902
private String getSchemaDescription(Attribute<?,?> attribute) {
906903
return EntityIntrospector.introspect(attribute.getDeclaringType())
907904
.getSchemaDescription(attribute.getName())

graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/JpaPredicateBuilder.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
import java.util.Collection;
3131
import java.util.Date;
3232
import java.util.HashMap;
33+
import java.util.List;
3334
import java.util.Map;
3435
import java.util.Set;
3536
import java.util.UUID;
3637

3738
import javax.persistence.criteria.CriteriaBuilder;
3839
import javax.persistence.criteria.Expression;
3940
import javax.persistence.criteria.From;
40-
import javax.persistence.criteria.Join;
4141
import javax.persistence.criteria.Path;
4242
import javax.persistence.criteria.Predicate;
4343
import javax.persistence.metamodel.EntityType;
@@ -730,27 +730,21 @@ else if(Collection.class.isAssignableFrom(type)) {
730730
// collection join for plural attributes
731731
if(PluralAttribute.class.isInstance(from.getModel())
732732
|| EntityType.class.isInstance(from.getModel())) {
733+
Expression<? extends Collection<Object>> expression = from.get(filter.getField());
733734
Predicate predicate;
734-
735-
if(EntityType.class.isInstance(from.getModel())) {
736-
From<?,?> join = null;
737735

738-
for(Join<?,?> fetch: from.getJoins()) {
739-
if(fetch.getAttribute().getName().equals(filter.getField()))
740-
join = (From<?,?>) fetch;
741-
}
736+
if(Collection.class.isInstance(filter.getValue())) {
737+
List<Predicate> restrictions = new ArrayList<>();
742738

743-
if(join == null) {
744-
join = (From<?,?>) from.join(filter.getField());
745-
}
739+
Collection.class.cast(filter.getValue())
740+
.forEach(v -> restrictions.add(cb.isMember(v, expression)));
741+
742+
predicate = cb.and(restrictions.toArray(new Predicate[] {}));
746743

747-
predicate = join.in(value);
748744
} else {
749-
Expression<? extends Collection<Object>> expression = from.get(filter.getField());
750-
751745
predicate = cb.isMember(filter.getValue(), expression);
752746
}
753-
747+
754748
if(filter.anyMatch(Criteria.NIN, Criteria.NE)) {
755749
return cb.not(predicate);
756750
}

0 commit comments

Comments
 (0)