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

橙三吉。 提交于 2019-12-05 07:43:36

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<T> 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<String, Object> 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<SomeEntity, Long>, QueryDslPredicateExecutor<SomeEntity>, SomeRepositoryCustom {
}


public interface SomeRepositoryCustom {
    Page<SomeEntity> findAll(Predicate predicate, Pageable pageable);
}

public class SomeRepositoryImpl extends SimpleJpaRepository<SomeEntity, Long>
    implements SomeEntityRepositoryCustom
{
    private final EntityManager entityManager;
    private final EntityPath<SomeEntity> path;
    private final PathBuilder<SomeEntity> 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<SomeEntity> 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<SomeEntity> content = total > pageable.getOffset() ? query.list(path) :
            Collections.<SomeEntity> 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!