Skip to content

EmbeddedId management #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 0 commits into from

Conversation

ludovicmotte
Copy link

Hi,
This is a new feature : managing JPA @EmbeddedId
Best regards.

@igdianov igdianov self-requested a review January 25, 2019 21:12
@igdianov
Copy link
Collaborator

igdianov commented Jan 25, 2019

@ludovicmotte Thank you very much for your PR! I really dig the feature to enable support for @EmbeddableId, but implementation only works for single entity queries.

The where criteria expression schema should only enable using EQ operator with all attributes of EmbeddableId class required. I would expect the following plural entity query to be resolved as follows:

    @Test
    public void queryForEntitiesWithEmeddableTypeAndWhereEmbeddableId() {
        //given
        String query = "{ Boats(where: {boatId: {EQ: {id: \"1\" country: \"EN\"}}}) { select { boatId {id country} engine { identification } } } }";

        String expected = "{Boats={select=[{boatId={id=1, country=EN}, engine={identification=12345}}]}}";

        //when
        Object result = executor.execute(query).getData();

        // then
        assertThat(result.toString()).isEqualTo(expected);
    }

This test fails with the following exception:

java.lang.IllegalArgumentException: Unsupported field type class com.introproventures.graphql.jpa.query.schema.model.embedded.Boat$BoatId for field boatId
	at com.introproventures.graphql.jpa.query.schema.impl.JpaPredicateBuilder.getTypedPredicate(JpaPredicateBuilder.java:370) ~[classes/:na]
	at com.introproventures.graphql.jpa.query.schema.impl.JpaPredicateBuilder.getPredicate(JpaPredicateBuilder.java:384) ~[classes/:na]
	at com.introproventures.graphql.jpa.query.schema.impl.QraphQLJpaBaseDataFetcher.lambda$25(QraphQLJpaBaseDataFetcher.java:397) ~[classes/:na]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]

@codecov
Copy link

codecov bot commented Jan 25, 2019

Codecov Report

Merging #62 into master will increase coverage by 1.96%.
The diff coverage is 93.33%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master      #62      +/-   ##
============================================
+ Coverage      60.4%   62.37%   +1.96%     
+ Complexity      283      269      -14     
============================================
  Files            31       21      -10     
  Lines          1816     1632     -184     
  Branches        282      253      -29     
============================================
- Hits           1097     1018      -79     
+ Misses          593      508      -85     
+ Partials        126      106      -20
Impacted Files Coverage Δ Complexity Δ
...query/schema/impl/GraphQLJpaSimpleDataFetcher.java 91.3% <92.85%> (+1.3%) 7 <6> (+4) ⬆️
...jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java 88.2% <93.4%> (+2.25%) 72 <19> (+2) ⬆️
...ventures/graphql/jpa/query/schema/JavaScalars.java 24.41% <0%> (-8.5%) 3% <0%> (ø)
...hql/jpa/query/schema/impl/JpaPredicateBuilder.java 41.42% <0%> (-3.25%) 29% <0%> (-11%)
...graphql/jpa/query/schema/impl/PredicateFilter.java 96% <0%> (-0.3%) 4% <0%> (ø)
...utoconfigure/GraphQLJpaQueryAutoConfiguration.java 100% <0%> (ø) 1% <0%> (ø) ⬇️
...tures/graphql/jpa/query/web/GraphQLController.java
...s/graphql/jpa/query/example/starwars/CodeList.java
...oconfigure/GraphQLControllerAutoConfiguration.java
...ntures/graphql/jpa/query/example/books/Author.java
... and 21 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 12caf3a...12caf3a. Read the comment docs.

@igdianov
Copy link
Collaborator

@ludovicmotte There could be other use cases where embedable ids criteria expressions could be more comlex, i.e.

{ Boats(where: {boatId: { id: {LIKE: "1"} country: {NIN: ["EN"]} } } ) { select { boatId {id country} engine { identification } } } }

What do you think? Is it something that could be useful? The EQ use case could be expressed as follows:

{ Boats(where: {boatId: { id: {EQ: "1"} country: {EQ: "EN"} } } ) { select { boatId {id country} engine { identification } } } }

@ludovicmotte
Copy link
Author

@igdianov Thanks for the review, I understand your point.
I think that for multiple entity queries you could consider EmbeddedId as Embedded (both are Embeddable):

    @Test
    public void queryForEntitiesWithWithEmbeddedIdWithWhere() {
        //given
        String query = "{ Boats { select { boatId(where: { AND: {id: { LIKE: \"1\"} country: { EQ: \"EN\"}}}) {id country} engine { identification } } } }";

        String expected = "{Boats={select=[{boatId={id=1, country=EN}, engine={identification=12345}}]}}";

        //when
        Object result = executor.execute(query).getData();

        // then
        assertThat(result.toString()).isEqualTo(expected);
    }

What do you think about it ? It can also cover your complex criteria expressions.

To sum up:

  • EmbeddedId and Embedded are both Embeddable and can use the "Reverse Query" syntax with where arg.

  • EmbeddedId can be part of the Singular Query syntax, with all values of the key (the AND operator is implicit in this case)

You can see the fix of pr/62/merge in my repo.

Best regards,
ludovicmotte

@igdianov
Copy link
Collaborator

igdianov commented Feb 4, 2019

@ludovicmotte I like your proposal to use reverse query syntax with where in query field for @EmbeddableId, but the the explicit AND operator seems to be redundant since AND is always used implicitly by convention. Do you think you can make it implicit by default?

@ludovicmotte
Copy link
Author

Oups, I closed my pull request without knowing it, but I still want to contribute !
@igdianov My previous test already works if you write with an implicit AND :

String query = "{ Boats { select { boatId(where: {id: { LIKE: \"1\"} country: { EQ: \"EN\"}}) {id country} engine { identification } } } }";

Is it what you were exepecting ?

@ludovicmotte
Copy link
Author

NB : your sample application seems not to work anymore:

2019-02-10 18:13:30.229 ERROR 4964 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQLSchemaFactoryBean' defined in class path resource [com/introproventures/graphql/jpa/query/autoconfigure/GraphQLSchemaAutoConfiguration.class]: Invocation of init method failed; nested exception is graphql.AssertException: queryType can't be null
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:827) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at com.introproventures.graphql.jpa.query.example.Application.main(Application.java:33) [classes/:na]
Caused by: graphql.AssertException: queryType can't be null
	at graphql.Assert.assertNotNull(Assert.java:13) ~[graphql-java-11.0.jar:na]
	at graphql.schema.GraphQLSchema.<init>(GraphQLSchema.java:62) ~[graphql-java-11.0.jar:na]
	at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:340) ~[graphql-java-11.0.jar:na]
	at com.introproventures.graphql.jpa.query.autoconfigure.GraphQLSchemaFactoryBean.createInstance(GraphQLSchemaFactoryBean.java:57) ~[classes/:na]
	at com.introproventures.graphql.jpa.query.autoconfigure.GraphQLSchemaFactoryBean.createInstance(GraphQLSchemaFactoryBean.java:13) ~[classes/:na]
	at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:142) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
	... 16 common frames omitted

@ludovicmotte ludovicmotte mentioned this pull request Feb 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants