diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java index d831cd0a4..70352052f 100644 --- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java @@ -36,13 +36,7 @@ import javax.persistence.Convert; import javax.persistence.EntityManager; import javax.persistence.Transient; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.EmbeddableType; -import javax.persistence.metamodel.EntityType; -import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.Type; +import javax.persistence.metamodel.*; import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription; import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnore; @@ -581,7 +575,7 @@ private List getEntityAttributesFields(EntityType ent return entityType.getAttributes() .stream() .filter(this::isNotIgnored) - .map(this::getObjectField) + .map(it -> getObjectField(it, entityType)) .collect(Collectors.toList()); } @@ -608,9 +602,13 @@ private GraphQLFieldDefinition getJavaFieldDefinition(PropertyDescriptor propert .dataFetcher(dataFetcher) .build(); } - - @SuppressWarnings( { "rawtypes", "unchecked" } ) + private GraphQLFieldDefinition getObjectField(Attribute attribute) { + return getObjectField(attribute, null); + } + + @SuppressWarnings( { "rawtypes", "unchecked" } ) + private GraphQLFieldDefinition getObjectField(Attribute attribute, EntityType baseEntity) { GraphQLOutputType type = getAttributeOutputType(attribute); List arguments = new ArrayList<>(); @@ -640,11 +638,11 @@ && isNotIgnoredOrder(attribute) ) { else if (attribute instanceof PluralAttribute && (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.ONE_TO_MANY || attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.MANY_TO_MANY)) { - EntityType declaringType = (EntityType) ((PluralAttribute) attribute).getDeclaringType(); - ManagedType elementType = getForeignType(attribute); + Assert.assertNotNull(baseEntity, "For attribute "+attribute.getName() + " cannot find declaring type!"); + EntityType elementType = (EntityType) ((PluralAttribute) attribute).getElementType(); arguments.add(getWhereArgument(elementType)); - dataFetcher = new GraphQLJpaOneToManyDataFetcher(entityManager, declaringType, (PluralAttribute) attribute); + dataFetcher = new GraphQLJpaOneToManyDataFetcher(entityManager, baseEntity, (PluralAttribute) attribute); } return GraphQLFieldDefinition.newFieldDefinition() diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorSuperClassTests.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorSuperClassTests.java new file mode 100644 index 000000000..a173e7c8e --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorSuperClassTests.java @@ -0,0 +1,85 @@ +package com.introproventures.graphql.jpa.query.schema; + + +import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutor; +import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSchemaBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.Assert; + +import javax.persistence.EntityManager; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.NONE) +@TestPropertySource({"classpath:hibernate.properties"}) +public class GraphQLExecutorSuperClassTests { + + @SpringBootApplication + static class Application { + @Bean + public GraphQLExecutor graphQLExecutor(final GraphQLSchemaBuilder graphQLSchemaBuilder) { + return new GraphQLJpaExecutor(graphQLSchemaBuilder.build()); + } + + @Bean + public GraphQLSchemaBuilder graphQLSchemaBuilder(final EntityManager entityManager) { + + return new GraphQLJpaSchemaBuilder(entityManager) + .name("GraphQLBooks") + .description("Books JPA test schema"); + } + } + + @Autowired + private GraphQLExecutor executor; + + @Test + public void contextLoads() { + Assert.isAssignable(GraphQLExecutor.class, executor.getClass()); + } + + + @Test + public void querySuperAuthors() { + //given + String query = "{ SuperAuthors { select { id name genre} }}"; + + String expected = "{SuperAuthors={select=[" + + "{id=1, name=Leo Tolstoy, genre=NOVEL}, " + + "{id=4, name=Anton Chekhov, genre=PLAY}" + + "]}}"; + + //when + Object result = executor.execute(query).getData(); + + // then + assertThat(result.toString()).isEqualTo(expected); + } + + @Test + public void querySuperBooks() { + //given + String query = "{ SuperBooks(where: {genre: {IN: PLAY}}) { select { id title, genre } }}"; + + String expected = "{SuperBooks={select=[" + + "{id=5, title=The Cherry Orchard, genre=PLAY}, " + + "{id=6, title=The Seagull, genre=PLAY}, " + + "{id=7, title=Three Sisters, genre=PLAY}" + + "]}}"; + + //when + Object result = executor.execute(query).getData(); + + // then + assertThat(result.toString()).isEqualTo(expected); + } +} + diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseAuthor.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseAuthor.java new file mode 100644 index 000000000..0b13c4e4d --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseAuthor.java @@ -0,0 +1,30 @@ +package com.introproventures.graphql.jpa.query.schema.model.book_superclass; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +@MappedSuperclass +@Getter +@Setter +public class BaseAuthor { + @Id + Long id; + + @OneToMany(mappedBy="author", fetch= FetchType.LAZY) + Collection books; + + @ElementCollection(fetch=FetchType.LAZY) + @CollectionTable(name = "author_phone_numbers", joinColumns = @JoinColumn(name = "author_id")) + @Column(name = "phone_number") + private Set phoneNumbers = new HashSet<>(); + + @Enumerated(EnumType.STRING) + SuperGenre genre; + + +} diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseBook.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseBook.java new file mode 100644 index 000000000..56eefae83 --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/BaseBook.java @@ -0,0 +1,23 @@ +package com.introproventures.graphql.jpa.query.schema.model.book_superclass; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.util.Date; + +@MappedSuperclass +@Getter +@Setter +public class BaseBook { + @Id + Long id; + + @ManyToOne(fetch= FetchType.LAZY) + SuperAuthor author; + + @Enumerated(EnumType.STRING) + SuperGenre genre; + + Date publicationDate; +} diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperAuthor.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperAuthor.java new file mode 100644 index 000000000..3f6de21a4 --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperAuthor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema.model.book_superclass; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.*; + +@Entity +@Table(name = "author") +@Getter +@Setter +@ToString +@EqualsAndHashCode(exclude={"books","phoneNumbers"}) // Fixes NPE in Hibernate when initializing loaded collections #1 +public class SuperAuthor extends BaseAuthor { + + String name; + +} diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperBook.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperBook.java new file mode 100644 index 000000000..41f103da6 --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperBook.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema.model.book_superclass; + +import lombok.Data; + +import javax.persistence.*; +import java.util.Date; + +@Data +@Entity +@Table(name = "book") +public class SuperBook extends BaseBook { + + String title; + +} diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperGenre.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperGenre.java new file mode 100644 index 000000000..cb51f41b7 --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/model/book_superclass/SuperGenre.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema.model.book_superclass; + +public enum SuperGenre { + NOVEL, PLAY +} diff --git a/graphql-jpa-query-schema/src/test/resources/hibernate.properties b/graphql-jpa-query-schema/src/test/resources/hibernate.properties index e226fbed0..5045f52f0 100644 --- a/graphql-jpa-query-schema/src/test/resources/hibernate.properties +++ b/graphql-jpa-query-schema/src/test/resources/hibernate.properties @@ -3,6 +3,6 @@ org.hibernate.stat=DEBUG spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.format_sql=true -logging.level.org.hibernate=debug +logging.level.org.hibernate=info #logging.level.org.hibernate.type.descriptor.sql=trace #logging.level.org.hibernate.SQL=debug