spring-projects / spring-data-jpa

Simplifies the development of creating a JPA-based data access layer.
https://spring.io/projects/spring-data-jpa/
Apache License 2.0
3.01k stars 1.42k forks source link

Spring data specification is not working as expected with pageable #3224

Closed mdadil-dk closed 3 months ago

mdadil-dk commented 1 year ago

Environment:

We are working with Spring Data specification for creating dynamic queries and have Pagination. Getting the following error in some cases where we change the values of Pageable size and page.

org.springframework.orm.jpa.JpaSystemException: Could not locate TableGroup - com.example.ganymede.report.data.models.ReportsEntity(357331951142118)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:320)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:229)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
        at jdk.proxy4/jdk.proxy4.$Proxy157.findAll(Unknown Source)
    ......

Specification:

final String isDeleted = ReportsEntity.Fields.isDeleted;
final List<Predicate> predicates = new ArrayList<>();
final Specification<T> tSpecification =
        (root, cq, builder) -> {
                predicates.add(builder.equal(root.get(isDeleted), Boolean.FALSE));

                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
        };

Pageable:

PageRequest.of(page.getNumber() - 1, page.getSize(), Sort.by(direction, sortAttribute));
Repository:

@EnableJpaRepositories
public interface ReportsRepository extends JpaRepository<ReportsEntity, Long>,
                JpaSpecificationExecutor<ReportsEntity> {

    Page<UserReportsEntity> findAll(Specification spec, Pageable pageable);                

}

The current change is working as expected in a few cases but failing in other cases.

Working case: Suppose the total rows in the reports table are 15 and if we make the Pageable request. Here, the page.number * page.size is around the total number of rows in the database table.

{attribute: "createdAt", direction: DESC}

 "page": {
    "number": 1,
    "size": 16
  }

//or
"page": {
    "number": 2,
    "size": 8
  }

//or
"page": {
    "number": 3,
    "size": 6
  }

Failed case:

"page": {
    "number": 3,
    "size": 8
  }

//or
"page": {
    "number": 1,
    "size": 8
  }

//or
"page": {
    "number": 2,
    "size": 15
  }

The above specification is a basic filter, it will be dynamic and should able to handle mutiples columns to query across multiple Join tables. is the above behavior of Specification and pageable expected? Did we miss some configuration or any other changes?

Full stack trace:

2023-11-10 14:13:50.447 IST [http-nio-3031-exec-4] [DEBUG] o.s.web.servlet.DispatcherServlet [LogFormatUtils.java:120] [] [] - POST "/graphql", parameters={}
2023-11-10 14:13:50.448 IST [http-nio-3031-exec-4] [DEBUG] o.s.w.s.m.m.a.RequestMappingHandlerMapping [AbstractHandlerMapping.java:528] [] [] - Mapped to com.netflix.graphql.dgs.mvc.DgsRestController#graphql(InputStream, HttpHeaders, WebRequest)
2023-11-10 14:13:50.460 IST [http-nio-3031-exec-4] [DEBUG] org.hibernate.SQL [SqlStatementLogger.java:133] [] [] - 
    /* <criteria> */ select
        u1_0.id,
        u1_0.emails,
    u1_0.created_at,
        u1_0.is_deleted,
    u1_0.last_modified_at,
    u1_0.last_modified_by,
        u1_0.name,
        u1_0.saved_by,
        u1_0.status,
        u1_0.status_comment,
        u1_0.type
    from
        reports u1_0 
    where
        u1_0.is_deleted=? 
    order by
        u1_0.created_at desc offset ? rows fetch first ? rows only
Hibernate: 
    /* <criteria> */ select
        u1_0.id,
        u1_0.emails,
    u1_0.created_at,
        u1_0.is_deleted,
    u1_0.last_modified_at,
    u1_0.last_modified_by,
        u1_0.name,
        u1_0.saved_by,
        u1_0.status,
        u1_0.status_comment,
        u1_0.type 
    from
        reports u1_0 
    where
        u1_0.is_deleted=? 
    order by
        u1_0.created_at desc offset ? rows fetch first ? rows only
2023-11-10 14:13:50.479 IST [http-nio-3031-exec-4] [ERROR] c.n.g.d.e.DefaultDataFetcherExceptionHandler [DefaultDataFetcherExceptionHandler.kt:46] [] [] - Exception while executing data fetcher for /listReports: Could not locate TableGroup - com.example.ganymede.report.data.models.ReportsEntity(396507765603252)
org.springframework.orm.jpa.JpaSystemException: Could not locate TableGroup - com.example.ganymede.report.data.models.ReportsEntity(396507765603252)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:320)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:229)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
    at jdk.proxy3/jdk.proxy3.$Proxy155.findAll(Unknown Source)
    at com.example.ganymede.report.api.services.ReportServiceImpl.listReports(ReportServiceImpl.java:91)
    at com.example.ganymede.report.api.controllers.graphql.ReportsDataFetcher.listReports(ReportsDataFetcher.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97)
    at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113)
    at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod$kotlin_reflection(KCallableImpl.kt:188)
    at kotlin.reflect.jvm.internal.KCallableImpl.callBy(KCallableImpl.kt:111)
    at com.netflix.graphql.dgs.internal.DataFetcherInvoker.invokeKotlinMethod(DataFetcherInvoker.kt:106)
    at com.netflix.graphql.dgs.internal.DataFetcherInvoker.get(DataFetcherInvoker.kt:63)
    at graphql.schema.DataFetcherFactories.lambda$wrapDataFetcher$2(DataFetcherFactories.java:37)
    at graphql.execution.ExecutionStrategy.invokeDataFetcher(ExecutionStrategy.java:309)
    at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:286)
    at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:212)
    at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:55)
    at graphql.execution.Execution.executeOperation(Execution.java:161)
    at graphql.execution.Execution.execute(Execution.java:104)
    at graphql.GraphQL.execute(GraphQL.java:557)
    at graphql.GraphQL.lambda$parseValidateAndExecute$11(GraphQL.java:476)
    at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
    at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
    at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:471)
    at graphql.GraphQL.executeAsync(GraphQL.java:439)
    at com.netflix.graphql.dgs.internal.BaseDgsQueryExecutor.baseExecute(BaseDgsQueryExecutor.kt:120)
    at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.execute(DefaultDgsQueryExecutor.kt:83)
    at com.netflix.graphql.dgs.mvc.DgsRestController$executeQuery$executionResult$1.invoke(DgsRestController.kt:212)
    at com.netflix.graphql.dgs.mvc.DgsRestController$executeQuery$executionResult$1.invoke(DgsRestController.kt:210)
    at com.netflix.graphql.dgs.internal.utils.TimeTracer.logTime(TimeTracer.kt:24)
    at com.netflix.graphql.dgs.mvc.DgsRestController.executeQuery(DgsRestController.kt:210)
    at com.netflix.graphql.dgs.mvc.DgsRestController.graphql(DgsRestController.kt:132)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.hibernate.sql.ast.SqlTreeCreationException: Could not locate TableGroup - com.example.ganymede.report.data.models.ReportsEntity(396507765603252)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.prepareReusablePath(BaseSqmToSqlAstConverter.java:3615)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.prepareReusablePath(BaseSqmToSqlAstConverter.java:3562)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.prepareReusablePath(BaseSqmToSqlAstConverter.java:3551)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitBasicValuedPath(BaseSqmToSqlAstConverter.java:4169)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitBasicValuedPath(BaseSqmToSqlAstConverter.java:434)
    at org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath.accept(SqmBasicValuedSimplePath.java:132)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitComparisonPredicate(BaseSqmToSqlAstConverter.java:7307)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitComparisonPredicate(BaseSqmToSqlAstConverter.java:434)
    at org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate.accept(SqmComparisonPredicate.java:104)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitJunctionPredicate(BaseSqmToSqlAstConverter.java:6967)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitJunctionPredicate(BaseSqmToSqlAstConverter.java:434)
    at org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate.accept(SqmJunctionPredicate.java:74)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitWhereClause(BaseSqmToSqlAstConverter.java:2476)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:2053)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:434)
    at org.hibernate.query.sqm.tree.select.SqmQuerySpec.accept(SqmQuerySpec.java:125)
    at org.hibernate.query.sqm.spi.BaseSemanticQueryWalker.visitQueryPart(BaseSemanticQueryWalker.java:221)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQueryPart(BaseSqmToSqlAstConverter.java:1907)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:1592)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:434)
    at org.hibernate.query.sqm.tree.select.SqmSelectStatement.accept(SqmSelectStatement.java:222)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.translate(BaseSqmToSqlAstConverter.java:775)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.buildCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:345)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:268)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:244)
    at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:518)
    at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:367)
    at org.hibernate.query.Query.getResultList(Query.java:119)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.executeCountQuery(SimpleJpaRepository.java:912)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.lambda$readPage$3(SimpleJpaRepository.java:697)
    at org.springframework.data.support.PageableExecutionUtils.getPage(PageableExecutionUtils.java:70)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.readPage(SimpleJpaRepository.java:696)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:448)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    ... 89 common frames omitted
2023-11-10 14:13:50.480 IST [http-nio-3031-exec-4] [DEBUG] o.s.w.s.m.m.a.HttpEntityMethodProcessor [AbstractMessageConverterMethodProcessor.java:275] [] [] - Using 'application/json', given [application/json] and supported [application/json]
2023-11-10 14:13:50.480 IST [http-nio-3031-exec-4] [DEBUG] o.s.w.s.m.m.a.HttpEntityMethodProcessor [LogFormatUtils.java:120] [] [] - Writing [{errors=[{message=org.springframework.orm.jpa.JpaSystemException: Could not locate TableGroup - com. (truncated)...]
2023-11-10 14:13:50.481 IST [http-nio-3031-exec-4] [DEBUG] o.s.web.servlet.DispatcherServlet [FrameworkServlet.java:1135] [] [] - Completed 200 OK

StackOverflow Hibernate Forum

Edited- Full stack trace

mp911de commented 1 year ago

Care to attach the full stack trace? The one is truncated and doesn't show the actual cause.

mdadil-dk commented 1 year ago

@mp911de Have updated the full stack trace in issue

mp911de commented 1 year ago

Alright. Thanks a lot. With

Caused by: org.hibernate.sql.ast.SqlTreeCreationException: Could not locate TableGroup - com.example.ganymede.report.data.models.ReportsEntity(396507765603252)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.prepareReusablePath(BaseSqmToSqlAstConverter.java:3615)

you can post the full stack trace at the Hibernate forums as the underlying cause is a Hibernate exception. The top-most exception, org.springframework.orm.jpa.JpaSystemException is part of Spring's exception translation mechanism so that libraries using JPA do not need to handle vendor-specific exceptions.

Let me know how the Forum discussion goes. I will leave this ticket open until we get further guidance from the Hibernate team.

spring-projects-issues commented 12 months ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues commented 11 months ago

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

mfrechePgest commented 4 months ago

Hey ! I don't know if I should bump this previous issue or create a new one but...

OP did post his issue in Hibernate forums and issue is kinda stuck there too.

It seems i'm having myself trouble with this same issue.

Debugging between Spring-JPA & Hibernate-SQM isn't really my thing but it seems the issue comes from the underlying countQuery from SimpleJpaRepository when using a Pageable.

Debugging in BaseSqmToSqlAstConverter.prepareReusablePath (from Hibernate-core) shows me the first set of requests, coming from SimpleJpaRepository.findAll(Specification, Pageable) seems to work fine.

But the second request coming from SimpleJpaRepository.executeCountQuery crashes with the same error from OP. When it comes in prepareReusablePath from here, ids of NavigablePath don't match anymore (like if JPA Root weren't the same anymore or something like that).

I use Spring Boot 3.3.1 with provided Spring Data JPA 3.3.1 Hibernate-Core 6.5.2.Final

christophstrobl commented 4 months ago

@mfrechePgest if you have something like a minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem please feel free to reopen this issue since it was auto closed due to lack of feedback. Thank you!

mfrechePgest commented 4 months ago

@christophstrobl Thanks ! Here is a sample repo with the issue. https://github.com/mfrechePgest/spring-data-3224

Just run Junit test, it should crash

Writing it showed me the crash occurs when there's more results than the requested page size. In our production environment, the bug sounded kinda "random"... but it wasn't related to some data after all.

mfrechePgest commented 4 months ago

@christophstrobl Sry for spam but you told me to

feel free to reopen this issue

Don't think I can do this myself ? How ?

mfrechePgest commented 4 months ago

Update :

I found a fix in the simple repo Issue seems to come from the fact that filters are kept in specification attributes.

In my real production repository, Specification is obviously more complicated but we can refactor it so we don't have any instance attributes.

Can't say if there's an underlying bug anyway, but at least i've got a workaround.

EDIT : And OP had the same thing too : his List<Predicate> was outside of his lambda.