2014-11-04 12 views
6

Metody pochodzą z JpaSpecificationExecutor są niewystarczające, żaden z nich daje mi to, czego chcą:Jak wyłączyć liczenie, gdy Specyfikacja i Pageable są używane razem?

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

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

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

Pierwsza metoda wykonuje zapytanie numeracją stron i zapytania count. Następne 2 nie wykonują w ogóle stronicowania. Co potrzebne jest jedno z poniższych:

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

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

Poprzez rozszerzenie JpaSpecificationExecutor nie byłem w stanie dostać zarówno zapytania wykonywane, ale tak było zapytanie count. W mojej sytuacji należy unikać liczenia zapytań, ponieważ jest bardzo kosztowne. Pytanie brzmi: jak?

+0

możliwe duplikat [? Sposób wyłączania zapytanie liczyć od PageRequest uzyskania całkowitą liczbę stron] (http://stackoverflow.com/questions/ 12644749/sposób-wyłączyć-liczenie-zapytań-od-strony-żądania-do-całkowitych-stron) – mttdbrd

+0

Ta odpowiedź wydaje się być dostępna tutaj: http://stackoverflow.com/questions/12644749/way-to-disable- count-query-from-pagerequest-for-getting-total-pages? rq = 1 – mttdbrd

+1

Niezupełnie. Szukam rozwiązania dla Specification a.k.a search kryteriów. Czytając SimpleJpaRepository.findAll (spec, pageable), wygląda na to, że implementatorzy uważają, że zapytanie zliczające powinno zawsze być wykonywane najpierw, a jeśli plasterek jest poza zakresem, to nie wykona kwerendy wyboru. Nie wierzę, że liczenie zapytań zawsze jest mniej kosztowne. –

Odpowiedz

7

Przeglądanie metod za pomocą metod i readPage(TypedQuery, Pageable, Specification). Wydaje realizacja sprężyny jest zawsze wykonywać kwerendy policzyć i sprawdzić czy startIndex jest poza zakresem przed wykonaniem kwerendy wybierającej:

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); 
} 

nie wierzę, to jest zawsze najlepsza praktyka. W moim przykładzie użycia, na przykład, z przyjemnością wykonamy kwerendę raz z góry, a nie w kolejnych wywołaniach, ponieważ wiemy, że nowe dane nie pojawiają się wystarczająco często, aby zagwarantować aktualizację licznika, a kwerenda licznika jest bardzo kosztowna do wykonania.

Byłoby wspaniale, gdyby Spring Data mogła dostarczyć flagę lub alternatywną metodę wyłączenia liczenia dla zapytania o kryteria, podobną do simple find queries.

W tym czasie, oto moja praca wokół rozwiązanie:

Załóż wewnętrzną klasę, która podklasy SimpleJpaRepository. Zastąp readPage, aby wyłączyć zapytanie o liczenie. Utwórz DAO, dodaj adnotację do @Repository i stwórz instancję klasy wewnętrznej, aby przekazać odpowiedni EntityManager. Wreszcie wstrzykiwać tej DAO gdziekolwiek kryteria wyszukiwania „no-count” ma zastosowanie:

@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()); 
     } 
    } 
} 
+0

Też muszę móc to zrobić. Czy znalazłeś łatwiejszy/lepszy sposób na to, bez użycia tego obejścia dookoła? Dzięki! – delux247

+0

Nie, niestety. I jestem całkiem zadowolony z tego rozwiązania. Lepszą poprawką byłoby, moim zdaniem, żądanie funkcji. –

+0

Tak, byłoby miło, gdyby to mogło być dodane do głównego projektu. Stwierdziłem, że to dziwne, że to już nie istnieje, ponieważ mają już koncepcję "Slice", której dokładnie szukam, ale nie ma wsparcia dla "Slice" z zapytaniami dynamicznymi (specyfikacje) - http://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.limit-query-result – delux247

Powiązane problemy