introproventures / graphql-jpa-query

Generate GraphQL Query Api for your JPA Entity Models
https://github.com/introproventures/graphql-jpa-query
Apache License 2.0
196 stars 54 forks source link

Single Result Queries losing the original Object Type with EmbeddedIds #376

Open darmaninmatt opened 1 year ago

darmaninmatt commented 1 year ago

Describe the bug

Hi @igdianov, we have encountered an error when issuing singular queries with embedded IDs which are annotated with a JPA Converter. The original type of one of the embeddable ID fields (in our case LocalDate) was lost during the flattenEmbeddedIdArguments method and is causing an issue with the JPA where it is expecting a LocalDate but a String is being passed to the relational value converter.

To Reproduce Steps to reproduce the behavior:

  1. Create an Entity class with an embeddable ID.
  2. Create an Embeddable ID class, including a LocalDate field.
  3. Create a JPA Converter class which transforms from String to LocalDate.
  4. Annotate the LocalDate field with the converter.
  5. Run a singular query (get by ID) including the LocalDate field.

Expected behavior The parameter is passed to the converter in the convertToDatabaseColumn as a LocalDate rather than a String.

Screenshots

2023-06-26T17:33:55.214+02:00 INFO 2564 --- [nio-8080-exec-1] c.i.g.j.q.s.impl.GraphQLJpaQueryFactory : GraphQL JPQL Single Result Query String:

2023-06-26T17:33:55.301+02:00 ERROR 2564 --- [nio-8080-exec-1] s.g.e.ExceptionResolversExceptionHandler : Unresolved PersistenceException for executionId 100b72db-2def-819e-70b5-dcf6b4aa724f jakarta.persistence.PersistenceException: Error attempting to apply AttributeConverter at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toRelationalValue(JpaAttributeConverterImpl.java:105) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.type.internal.ConvertedBasicTypeImpl.disassemble(ConvertedBasicTypeImpl.java:316) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.metamodel.mapping.Bindable.forEachJdbcValue(Bindable.java:149) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.sql.exec.spi.JdbcParameterBindings.registerParametersForEachJdbcValue(JdbcParameterBindings.java:92) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.sql.exec.spi.JdbcParameterBindings.registerParametersForEachJdbcValue(JdbcParameterBindings.java:82) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.SqmUtil.createValueBindings(SqmUtil.java:394) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.SqmUtil.createJdbcParameterBindings(SqmUtil.java:326) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.buildCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:393) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:300) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:276) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:571) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:363) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.QuerySqmImpl.list(QuerySqmImpl.java:1073) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.spi.AbstractSelectionQuery.getSingleResult(AbstractSelectionQuery.java:457) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at org.hibernate.query.sqm.internal.QuerySqmImpl.getSingleResult(QuerySqmImpl.java:1103) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] at com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaQueryFactory.querySingleResult(GraphQLJpaQueryFactory.java:280) ~[graphql-jpa-query-schema-1.0.2-SNAPSHOT.jar:1.0.2-SNAPSHOT] at com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSimpleDataFetcher.get(GraphQLJpaSimpleDataFetcher.java:48) ~[graphql-jpa-query-schema-1.0.2-SNAPSHOT.jar:1.0.2-SNAPSHOT] at org.springframework.graphql.execution.ContextDataFetcherDecorator.lambda$get$0(ContextDataFetcherDecorator.java:76) ~[spring-graphql-1.1.3.jar:1.1.3] at io.micrometer.context.ContextSnapshot.lambda$wrap$1(ContextSnapshot.java:92) ~[context-propagation-1.0.2.jar:1.0.2] at org.springframework.graphql.execution.ContextDataFetcherDecorator.get(ContextDataFetcherDecorator.java:76) ~[spring-graphql-1.1.3.jar:1.1.3] at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:282) ~[graphql-java-19.5.jar:na] at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:211) ~[graphql-java-19.5.jar:na] at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:59) ~[graphql-java-19.5.jar:na] at graphql.execution.Execution.executeOperation(Execution.java:159) ~[graphql-java-19.5.jar:na] at graphql.execution.Execution.execute(Execution.java:105) ~[graphql-java-19.5.jar:na] at graphql.GraphQL.execute(GraphQL.java:645) ~[graphql-java-19.5.jar:na] at graphql.GraphQL.lambda$parseValidateAndExecute$11(GraphQL.java:564) ~[graphql-java-19.5.jar:na] at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309) ~[na:na] at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:559) ~[graphql-java-19.5.jar:na] at graphql.GraphQL.executeAsync(GraphQL.java:527) ~[graphql-java-19.5.jar:na] at org.springframework.graphql.execution.DefaultExecutionGraphQlService.lambda$execute$2(DefaultExecutionGraphQlService.java:82) ~[spring-graphql-1.1.3.jar:1.1.3] at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:47) ~[reactor-core-3.5.5.jar:3.5.5] at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.5.jar:3.5.5] at reactor.core.publisher.Mono.subscribeWith(Mono.java:4551) ~[reactor-core-3.5.5.jar:3.5.5] at reactor.core.publisher.Mono.toFuture(Mono.java:5063) ~[reactor-core-3.5.5.jar:3.5.5] at org.springframework.core.ReactiveAdapterRegistry$ReactorRegistrar.lambda$registerAdapters$5(ReactiveAdapterRegistry.java:244) ~[spring-core-6.0.8.jar:6.0.8] at org.springframework.core.ReactiveAdapter.fromPublisher(ReactiveAdapter.java:121) ~[spring-core-6.0.8.jar:6.0.8] at org.springframework.web.servlet.function.DefaultAsyncServerResponse.create(DefaultAsyncServerResponse.java:186) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.web.servlet.function.ServerResponse.async(ServerResponse.java:250) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.graphql.server.webmvc.GraphQlHttpHandler.handleRequest(GraphQlHttpHandler.java:111) ~[spring-graphql-1.1.3.jar:1.1.3] at org.springframework.web.servlet.function.support.HandlerFunctionAdapter.handle(HandlerFunctionAdapter.java:107) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.8.jar:6.0.8] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.0.8.jar:6.0.8] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.8.jar:6.0] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.0.8.jar:6.0.8] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.8.jar:6.0] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.8.jar:6.0.8] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.8.jar:6.0.8] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.8.jar:6.0.8] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.8.jar:6.0.8] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.8.jar:6.0.8] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.8.jar:6.0.8] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.8.jar:10.1.8] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.time.LocalDate (java.lang.String and java.time.LocalDate are in module java.base of loader 'bootstrap') at com.rs2.dl.data.api.converters.DateConverter.convertToDatabaseColumn(DateConverter.java:9) ~[main/:na] at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toRelationalValue(JpaAttributeConverterImpl.java:99) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final] ... 81 common frames omitted **Desktop (please complete the following information):** - OS: Windows - Browser: Chrome - Version: 1.0.1-SNAPSHOT
igdianov commented 1 year ago

@bijgu1997 Thanks for the report. Please, create a PR with the reproducer test case, so I can debug it and fix the problem