Skip to main content

Sliceを使用した無限スクロールによるページ区切りのパフォーマンスの向上

このTipは@nkolosnjajiにより提出されました

無限スクロールのページ区切りでは、Spring Data Pageを使用してデータベースからエンティティを取得します。 これにより、2つのクエリーがトリガーされます。1つはエンティティをフェッチするためのクエリーで、2つ目はページングするアイテムの合計を決定するためのcount allクエリーです。無限スクロールには合計サイズに関する情報は必要ありませんが、ロードする次のページがある場合にのみ必要です。大規模なデータセットで作業する場合にコストのかかるcount allクエリーを回避するには、無限スクロールのパフォーマンスを向上させるPageの代わりにSliceを使用します。

フロントエンドの無限スクロールプラグインに情報を送信するために、カスタムHTTPヘッダX-Has-Next-Pageを使用します。

  • エンティティリポジトリに新しいメソッドを定義します。
Slice<YourEntity> findSliceBy(Pageable pageable);
  • web/rest/utilパッケージにあるPaginationUtil.javaに新しい静的メソッドを定義します。
public static HttpHeaders generateSliceHttpHeaders(Slice<?> slice) {
HttpHeaders headers = new HttpHeaders();
headers.add("X-Has-Next-Page", "" + slice.hasNext());
return headers;
}
  • RESTコントローラーを変更して、Pageの代わりにSliceを呼び出し、新しいHTTPヘッダーを生成するようにします。
@GetMapping("/<YourEntities>")
@Timed
public ResponseEntity<List<Repo>> getAllRepos(Pageable pageable)
throws URISyntaxException {
Slice<YourEntity> slice = repoRepository.findSliceBy(pageable);
HttpHeaders headers = PaginationUtil.generateSliceHttpHeaders(slice);
return new ResponseEntity<>(slice.getContent(), headers, HttpStatus.OK);
}
  • 新しいビューモデルをentity.controller.jsで定義します。
vm.hasNextPage = false;
  • 応答からHTTPヘッダー値を抽出し、それをビューモデルに割り当てます。
function onSuccess(data, headers) {
vm.hasNextPage = headers('X-Has-Next-Page') === "true";
...
}
  • <your-entities>.htmlで無限スクロールプラグインを使ったビューモデルを使用します。
<tbody infinite-scroll="vm.loadPage(vm.page + 1)" infinite-scroll-disabled="!vm.hasNextPage">