Cosium / spring-data-jpa-entity-graph

Spring Data JPA extension allowing full dynamic usage of EntityGraph on repositories
MIT License
469 stars 52 forks source link

QueryException on pagination query with default entity graph #31

Closed bertrand378 closed 4 years ago

bertrand378 commented 4 years ago

Hello,

I'm using spring-data-jpa-entity-graph 2.0.5 and i'm facing an issue with default entity graph in pagination queries. Here is my entity (relevant parts only) :

@Entity
@NamedEntityGraphs(
    value = {
        @NamedEntityGraph(
            name = "He.default",
            attributeNodes = {@NamedAttributeNode("practitioner")})
    })
public class He {
...

  @ManyToOne(fetch = FetchType.LAZY)
  private Customer customer;

  @ManyToOne(fetch = FetchType.LAZY)
  private User practitioner;

...

And here is the JPA repository :

interface HeRepository extends EntityGraphJpaRepository<He, Integer> {

Page<He> findByCustomer(Customer customer, Pageable pageable);

...

When I call findByCustomer and the results are >= of the page size : hibernate make a count query and throw the following exception :

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias0,role=com.example.He.practitioner,tableName=utilisateurs,tableAlias=user1_,origin=He he0_,columns={he0_.practitioner_id ,className=com.example.User}}] [select count(generatedAlias0) from com.example.He as generatedAlias0 where generatedAlias0.customer=:param0]; nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias0,role=com.example.He.practitioner,tableName=utilisateurs,tableAlias=user1_,origin=He he0_,columns={he0_.practitioner_id ,className=com.example.User}}] [select count(generatedAlias0) from com.example.He as generatedAlias0 where generatedAlias0.customer=:param0]

    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:373)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    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:153)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at com.cosium.spring.data.jpa.entity.graph.repository.support.RepositoryMethodEntityGraphExtractor$JpaEntityGraphMethodInterceptor.doInvoke(RepositoryMethodEntityGraphExtractor.java:159)
    at com.cosium.spring.data.jpa.entity.graph.repository.support.RepositoryMethodEntityGraphExtractor$JpaEntityGraphMethodInterceptor.invoke(RepositoryMethodEntityGraphExtractor.java:103)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.example.$Proxy181.findByCustomer(Unknown Source)

Thank you (and great job by the way !)

bertrand378 commented 4 years ago

Hello,

I didn't notice at first but this issue can be reproduced as well with an entity graph passed as a paremeter like such a method in JPARepository :

Page<He> findByCustomer(Customer customer, Pageable pageable, EntityGraph entityGraph);

Regards.

bertrand378 commented 4 years ago

Thank you very much ! ;) I'll give it a try asap.