2016-05-16 18 views
2

のカウントを回避する方法()、私は改ページとfindAllを使用したいが、カウントは常に戻り値の型はListでもあれば、実行されます。 これは本当に遅く、ページネーションの利点を失う可能性があるため、このカウントは必要ありません。QueryDsl SpringData JPAのfindAllは、私は春データJPAでQueryDSLを使用しようとしている

この問題の解決策はありますか?この情報は単に最初に必要とされて、私は私が必要と各ページのカウントを繰り返したくない場合は

Mysql too slow on simple query between two tables

は、これは、MySQLの上で約30秒を必要とし、count()ですコール。 QueryDslPredicateExecutor以来

+0

私たちといくつかのコードを共有してくださいことはできますか? 'count'クエリは、通常、ページングの一部であり、UIの総ページ数/結果の数を表示することができます。なぜあなたのケースで 'カウント '部分が遅いのですか? – miensol

答えて

4

findAll(Predicate, Pageable)の戻り値としてSliceを返すサポートしていませんので、カウントクエリは避けられないようです。しかし、新しいベースリポジトリインターフェイスを定義し、findAllメソッドを実装して、ページネーションのカウントクエリを発行しないようにすることができます。基本的には、この実装はフェッチう

public class SliceableRepositoryImpl<T, ID extends Serializable> 
     extends QueryDslJpaRepository<T, ID> 
     implements SliceableRepository<T, ID> { 
    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE; 
    private final EntityPath<T> path; 
    private final PathBuilder<T> builder; 
    private final Querydsl querydsl; 

    public SliceableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) { 
     super(entityInformation, entityManager); 
     path = DEFAULT_ENTITY_PATH_RESOLVER.createPath(entityInformation.getJavaType()); 
     this.builder = new PathBuilder<>(path.getType(), path.getMetadata()); 
     this.querydsl = new Querydsl(entityManager, builder); 
    } 

    @Override 
    public Page<T> findAll(Predicate predicate, Pageable pageable) { 
     int oneMore = pageable.getPageSize() + 1; 
     JPQLQuery query = createQuery(predicate) 
       .offset(pageable.getOffset()) 
       .limit(oneMore); 

     Sort sort = pageable.getSort(); 
     query = querydsl.applySorting(sort, query); 

     List<T> entities = query.list(path); 

     int size = entities.size(); 
     if (size > pageable.getPageSize()) 
      entities.remove(size - 1); 

     return new PageImpl<>(entities, pageable, pageable.getOffset() + size); 
    } 
} 

:よう、このイ​​ンタフェースを実装し、その後

/** 
* Interface for adding one method to all repositories. 
* 
* <p>The main motivation of this interface is to provide a way 
* to paginate list of items without issuing a count query 
* beforehand. Basically we're going to get one element more 
* than requested and form a {@link Page} object out of it.</p> 
*/ 
@NoRepositoryBean 
public interface SliceableRepository<T, ID extends Serializable> 
     extends JpaRepository<T, ID>, 
     QueryDslPredicateExecutor<T> { 

    Page<T> findAll(Predicate predicate, Pageable pageable); 
} 

:まず第一に、あなたは他のすべてのリポジトリの基本インタフェースとして使用されるインターフェイスを定義する必要があります要求されたサイズよりも1つ多い要素とし、その結果をPageの構築に使用します。

@EnableJpaRepositories(repositoryBaseClass = SliceableRepositoryImpl.class) 

そして最後に、あなたの基本インタフェースとしてSliceableRepositoryを拡張する:次に、あなたは、リポジトリ基本クラスとしてこの実装を使用するように春のデータを教えてください

public SomeRepository extends SliceableRepository<Some, SomeID> {} 
+1

あなたの答えをお寄せいただきありがとうございます。この問題は解決しましたが、最終的にはquerydsl + Spring Data JPAのためにいつも何らかの最適化が必要なようです。私はもっと標準化されたアプローチを探していました。再度、感謝します – Etantonio

関連する問題