Overriding Spring-Data-JPA default method annotating with EntityGraph causes QueryException

前端 未结 1 1217
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-05 08:09

I\'m trying to implement a EntityGraph with Data-JPA, since using QueryDslPredicateExecutor exposes the method findAll(Predicate, Pageable)

1条回答
  •  北海茫月
    2021-01-05 08:46

    I've faced with exactly the same problem and had a lot of fun debugging the spring source code. So the root cause is: spring is applying hints on the count query which leads to that error.

    QueryDslJpaRepository.java:

    @Override
    public Page findAll(Predicate predicate, Pageable pageable) {
    
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate));
    ....
    }
    
    protected JPQLQuery createQuery(Predicate... predicate) {
    
        JPAQuery query = querydsl.createQuery(path).where(predicate);
        CrudMethodMetadata metadata = getRepositoryMethodMetadata();
    
        if (metadata == null) {
            return query;
        }
    
        LockModeType type = metadata.getLockModeType();
        query = type == null ? query : query.setLockMode(type);
    
        for (Entry hint : getQueryHints().entrySet()) {
            query.setHint(hint.getKey(), hint.getValue());
        }
    
        return query;
    }
    

    And the workaround is: create a supporting interface to your repository interface and implement it overriding the query creation logic. Here is my midnight implementation (it is just a prototype which must be improved of course).

    public interface SomeRepository extends JpaRepository, QueryDslPredicateExecutor, SomeRepositoryCustom {
    }
    
    
    public interface SomeRepositoryCustom {
        Page findAll(Predicate predicate, Pageable pageable);
    }
    
    public class SomeRepositoryImpl extends SimpleJpaRepository
        implements SomeEntityRepositoryCustom
    {
        private final EntityManager entityManager;
        private final EntityPath path;
        private final PathBuilder builder;
        private final Querydsl querydsl;
    
        @Autowired
        public SomeRepositoryImpl(EntityManager entityManager) {
            super(SomeEntity.class, entityManager);
    
    
            CrudMethodMetadata metadata = getRepositoryMethodMetadata();
            this.entityManager = entityManager;
            this.path = SimpleEntityPathResolver.INSTANCE.createPath(SomeEntity.class);
            this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
            this.querydsl = new Querydsl(entityManager, builder);
        }
    
        @Override
        public Page findAll(Predicate predicate, Pageable pageable) {
            JPAQuery countQuery = createQuery(predicate);
            JPAQuery query = (JPAQuery) querydsl.applyPagination(pageable, createQuery(predicate));
    
            query.setHint(EntityGraph.EntityGraphType.LOAD.getKey(),
                entityManager.getEntityGraph("YOUR GRAPH KEY"));
    
            Long total = countQuery.count();
            List content = total > pageable.getOffset() ? query.list(path) :
                Collections. emptyList();
    
            return new PageImpl<>(content, pageable, total);
        }
    
        private JPAQuery createQuery(Predicate predicate) {
            return querydsl.createQuery(path).where(predicate);
        }
    
    }
    

    Looks like it is a bug and I'm going to submit it to the spring jpa jira.

    0 讨论(0)
提交回复
热议问题