복붙노트

[SPRING] 사양 및 Pageable을 함께 사용하는 경우 카운트를 비활성화하는 방법은 무엇입니까?

SPRING

사양 및 Pageable을 함께 사용하는 경우 카운트를 비활성화하는 방법은 무엇입니까?

JpaSpecificationExecutor와 함께 제공되는 메서드는 부적절합니다. 그 중 아무 것도 내가 원하는 것을 제공하지 않습니다.

Page<T> findAll(Specification<T> spec, Pageable pageable)

List<T> findAll(Specification<T> spec)

List<T> findAll(Specification<T> spec, Sort sort)

첫 번째 방법은 페이지 매김 된 쿼리와 카운트 쿼리를 실행합니다. 다음 2는 페이지 매김을 전혀 수행하지 않습니다. 내가 필요로하는 것은 다음 중 하나입니다 :

Slice<T> findAll(Specification<T> spec, Pageable pageable)

List<T> findAll(Specification<T> spec, Pageable pageable)

JpaSpecificationExecutor를 확장하지 않음으로써 두 쿼리를 모두 실행할 수 있었지만 카운트 쿼리도 마찬가지였습니다. 제 상황에서는 카운트 쿼리가 매우 비싸기 때문에 피해야합니다. 문제는 어떻게?

해결법

  1. ==============================

    1.SimpleJpaRepository의 findAll (Specification, Pageable) 및 readPage (TypedQuery, Pageable, Specification) 메소드를 살펴보십시오. Spring의 구현은 항상 count 쿼리를 수행하고 select 쿼리를 실행하기 전에 startIndex가 범위를 벗어나는 지 확인하는 것입니다.

    SimpleJpaRepository의 findAll (Specification, Pageable) 및 readPage (TypedQuery, Pageable, Specification) 메소드를 살펴보십시오. Spring의 구현은 항상 count 쿼리를 수행하고 select 쿼리를 실행하기 전에 startIndex가 범위를 벗어나는 지 확인하는 것입니다.

    protected Page<T> readPage(TypedQuery<T> query, Pageable pageable, Specification<T> spec) {
    
        query.setFirstResult(pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());
    
        Long total = QueryUtils.executeCountQuery(getCountQuery(spec));
        List<T> content = total > pageable.getOffset() ? query.getResultList() : Collections.<T> emptyList();
    
        return new PageImpl<T>(content, pageable, total);
    }
    

    나는 이것이 항상 최선의 방법이라고 생각하지 않는다. 예를 들어, 새로운 데이터가 카운트 업데이트를 보증 할만큼 자주 제공되지 않고 카운트 쿼리가 실행하는 데 많은 비용이 들기 때문에 카운트 쿼리를 한 번만 실행하면됩니다.

    Spring Data가 단순한 찾기 쿼리와 유사하게 criteria 쿼리에 대한 카운트를 비활성화하는 플래그 또는 대체 방법을 제공 할 수 있다면 좋을 것입니다.

    그 동안 내 해결 방법은 다음과 같습니다.

    SimpleJpaRepository를 하위 클래스로하는 내부 클래스를 만듭니다. countPage를 비활성화하려면 readPage를 재정의하십시오. DAO를 만들고 @Repository로 주석을 달고이 내부 클래스를 인스턴스화하여 올바른 EntityManager를 전달하십시오. 마지막으로 "카운트 없음"기준 검색이 적용될 수있는 곳이면 어디든지이 DAO를 삽입하십시오.

    @Repository
    public class CriteriaNoCountDao {
    
        @PersistenceContext
        protected EntityManager em;
    
        public <T, ID extends Serializable> Page<T> findAll(Specification<T> spec, Pageable pageable, Class<T> clazz){
            SimpleJpaNoCountRepository<T, ID> noCountDao = new SimpleJpaNoCountRepository<T, ID>(clazz, em);
            return noCountDao.findAll(spec, pageable);
        }
    
        /**
         * Custom repository type that disable count query.
         */
        public static class SimpleJpaNoCountRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
    
            public SimpleJpaNoCountRepository(Class<T> domainClass, EntityManager em) {
                super(domainClass, em);
            }
    
            /**
             * Override {@link SimpleJpaRepository#readPage(TypedQuery, Pageable, Specification)}
             */
            protected Page<T> readPage(TypedQuery<T> query, Pageable pageable, Specification<T> spec) {
                query.setFirstResult(pageable.getOffset());
                query.setMaxResults(pageable.getPageSize());
    
                List<T> content = query.getResultList();
    
                return new PageImpl<T>(content, pageable, content.size());
            }
        }
    }
    
  2. ==============================

    2.해당 링크에 표시된대로 사용자 정의 기본 repositoy impl을 작성하십시오. https://www.baeldung.com/spring-data-jpa-method-in-all-repositories

    해당 링크에 표시된대로 사용자 정의 기본 repositoy impl을 작성하십시오. https://www.baeldung.com/spring-data-jpa-method-in-all-repositories

    다음과 같은 메소드를 작성하십시오.

     public List<T> findAllBy(Specification<T> aSpecification, Pageable aPageable) {
        TypedQuery<T> query = getQuery(aSpecification, aPageable);
        query.setFirstResult((int) aPageable.getOffset());
        query.setMaxResults(aPageable.getPageSize());
        return query.getResultList();
    }
    
  3. from https://stackoverflow.com/questions/26738199/how-to-disable-count-when-specification-and-pageable-are-used-together by cc-by-sa and MIT license