2014-11-04 9 views
6

I metodi di venire con JpaSpecificationExecutor sono inadeguate, nessuno di loro mi danno quello che voglio:Come disabilitare il conteggio quando Specification e Pageable vengono utilizzati insieme?

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

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

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

Il primo metodo esegue la query impaginato e la query conteggio. I prossimi 2 non eseguono affatto l'impaginazione. Quello che mi serve è una delle seguenti:

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

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

Con che non si estende JpaSpecificationExecutor, sono stato in grado di ottenere entrambe le query eseguite, ma lo era anche la query conteggio. Nella mia situazione, la query di conteggio deve essere evitata perché è molto costosa. La domanda è come?

+0

possibile duplicato di [? Modo per disattivare interrogazione conteggio da PageRequest per ottenere pagine totali] (http://stackoverflow.com/questions/ 12644749/way-to-disable-count-query-da-pagerequest-per-ottenere-totale-pagine) – mttdbrd

+0

Questo sembra essere risposta qui: http://stackoverflow.com/questions/12644749/way-to-disable- count-query-from-pagerequest-for-getting-total-pages? rq = 1 – mttdbrd

+1

Non proprio. Sto cercando una soluzione per la specifica a.k.a ricerca criteri. Leggendo SimpleJpaRepository.findAll (spec, pageable), sembra che gli implementatori ritengano che una query di conteggio debba sempre essere eseguita per prima e se la slice non è nell'intervallo, non eseguirà la query di selezione. Non credo che la query di conteggio sia sempre meno costosa. –

risposta

7

Guardando a SimpleJpaRepository 's findAll(Specification, Pageable) e readPage(TypedQuery, Pageable, Specification) metodi. Sembra che l'implementazione di primavera è quello di eseguire sempre una query di conteggio e verificare se lo startIndex è fuori del campo prima di eseguire la query di selezione:

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

io non credo che questo è sempre la migliore pratica. Nel mio caso d'uso, ad esempio, siamo felici di eseguire la query di conteggio una volta in primo piano e non nelle chiamate successive perché sappiamo che i nuovi dati non vengono abbastanza frequentemente da giustificare un aggiornamento del conteggio e la query di conteggio è molto costosa da eseguire.

Sarebbe bello se Spring Data fosse in grado di fornire un flag o un metodo alternativo per disabilitare il conteggio per la query sui criteri, simile a simple find queries.

Nel frattempo, ecco la mia soluzione work-around:

Creare una classe interna che le sottoclassi SimpleJpaRepository. Sostituisci readPage per disabilitare la query di conteggio. Crea un DAO, annotalo con @Repository e crea un'istanza di questa classe interna per passare sul EntityManager corretto. Infine, iniettare questo DAO ovunque ricerca "no-count" criteri è applicabile:

@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

Devo anche essere in grado di farlo. Hai scoperto un modo più semplice/migliore per farlo senza usare questo work-over override? Grazie! – delux247

+0

No, sfortunatamente. E sono abbastanza soddisfatto di questa soluzione. A mio avviso, una soluzione migliore sarebbe una richiesta di funzionalità. –

+0

Sì, sarebbe bello se questo potesse essere aggiunto al progetto principale. Ho trovato strano che questo non esista già, perché hanno già il concetto di "Slice", che è esattamente quello che sto cercando, ma non c'è supporto per una "Slice" con query dinamiche (Specifiche) - http://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.limit-query-result – delux247

Problemi correlati