DBFluteでのPagingについておさらい


http://dbflute.sandbox.seasar.org/ja/tips-paging.html

DBFluteは、S2Pagerを利用しません。
ConditionBeanにPagingが機能が既に付与されています。

ex) BOOKに対してAuthorが30歳以上/登録日時の降順/PageSize20件でPaging検索
/- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
final int pageSize = 20;
final LdBookCB cb = new LdBookCB();
cb.query().queryAuthor().setAuthorAge_GreaterEqual(30);
cb.query().addOrderBy_RTime_Desc();
cb.paging(pageSize, 1);
final java.util.List lsFirstPage = dao.selectList(cb);

cb.paging(pageSize, 2);
final java.util.List lsSecoundPage = dao.selectList(cb);

cb.paging(pageSize, 3);
final java.util.List lsThirdPage = dao.selectList(cb);
- - - - - - - - -/

MySQL → limit/offset構文利用
Postgre → limit/offset構文利用
Firebird → first構文を利用
Oracle → rownum利用
DB2 → fetch first x rows only構文利用 ※OffsetはResultSetにてすっ飛ばし
SQLServer → TOP構文利用 ※OffsetはResultSetにてすっ飛ばし
Sybase → ※TOPを利用しようと思ったら Sybase-12.x ではサポートされていない!? (15.xかららしい)

Performanceを考慮します。ResultSetすっ飛ばしではなく極力DB自体の構文で実現。


Pagingの処理につきものなのが...

画面に表示する「前へ」・「次へ」などのリンク。
最初のページでは「前へ」は表示したくないし、最後のページでは「次へ」が要らない。
また、「Pagingにより絞り込みなしで検索した場合の最大件数」・「現在ページ番号」なども

これらをDBFluteでは以下のように取得することが可能です。

ex) BOOKに対してAuthorが30歳以上/登録日時の降順/PageSize20件でPaging検索
※該当のConditionBeanにて条件に合致する総Record数が76件だと仮定します。
/- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
final int pageSize = 20;
final LdBookCB cb = new LdBookCB();
cb.query().queryAuthor().setAuthorAge_GreaterEqual(30);
cb.query().addOrderBy_RTime_Desc();
cb.paging(pageSize , 1);// 1-20
final LdPagingResultBean rbFirstPage = bhv.selectPage(cb);
cb.paging(pageSize, 2);// 21-40
final LdPagingResultBean rbSecondPage = bhv.selectPage(cb);
cb.paging(pageSize, 3);// 41-60
final LdPagingResultBean rbThirdPage = bhv.selectPage(cb);
cb.paging(pageSize, 4);// 61-76
final LdPagingResultBean rbFourthPage = bhv.selectPage(cb);

// ***************************************
// 「1」Page目のPaging結果についてのAssert
// ***************************************

// 検索したTable名(結合の中心Table) → BOOK
assertEquals("BOOK", rbFirstPage.getTableDbName());

// 総Record数 → 76
assertEquals(76, rbFirstPage.getAllRecordCount());

// 該当PageのEntityのList → 件数はPageSizeと同じ
assertEquals(20, rbFirstPage.getSelectedList().size());

// OrderByの一番目の要素のASC/DESC → DESC
assertTrue(getOrderByClause().isFirstElementDesc());

// OrderByの一番目の要素の列名 → R_TIME
assertTrue(getOrderByClause().isSameAsFirstElementColumnName("R_TIME"));

// PageSize → 20
assertEquals(20, rbFirstPage.getPageSize());

// 現在のPage番号 → 1
assertEquals(1, rbFirstPage.getCurrentPageNumber());

// 総Page数 → 4 ※allRecordCountとpageSizeから計算
assertEquals(4, rbFirstPage.getAllPageCount());

// 前のPageがあるか否か → 現在は1Page目なのでFalse
assertFalse(rbFirstPage.isExistPrePage());

// 次のPageがあるか否か → 次の2Page目があるのでTrue
assertTrue(rbFirstPage.isExistNextPage());

// ***************************************
// 「2」Page目のPaging結果についてのAssert
// ***************************************
// ※共通部のAssertは省略{それらは1Page目と同じ値となります}

// 現在のPage番号 → 2
assertEquals(2, rbSecondPage.getCurrentPageNumber());

// 前のPageがあるか否か → 現在は2Page目なのでTrue
assertTrue(rbSecondPage.isExistPrePage());

// 次のPageがあるか否か → 次の3Page目があるのでTrue
assertTrue(rbSecondPage.isExistNextPage());

...(略:http://dbflute.sandbox.seasar.org/ja/tips-paging.html)
- - - - - - - - -/

PagingResultBeanというPaging専用戻り値Objectに上記の値を求める計算Logicが
既に用意されています。これらは、自分の周りのProjectにて実際に利用されていて、
Paging周りの画面表示リンクの処理は画面開発者が頑張る必要が全くありませんでした。

また、「1,2,3,4...」というページ番号のリンクもPaging検索画面では必ず表示します。
最大表示10ページまでに制限して、開いているページの前後5ページを表示したり、
11ページ目を開いている場合は「11,12,13,14...」と表示したりと要件によって色々。
「1,2,3,4...」のリンク表現の要素取得も2パターン用意されています。

{PageRange}

ex) 「ある限られたPage番号」は現在のPage番号の前後1Pageとした場合
※一般的には、前後5Pageとか前後10Pageとかが基本です。(例は総Page数が少ないので前後1Pageとします)
※これらは、設定されたPageRangeSizeとPaging結果を基に都度算出します。
/- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// **********************
// 「1」Page目のPageRange
// **********************
// PageRangeSizeは現在のPage番号の前後1Pageとする
rbFirstPage.setPageRangeSize(1);

// 該当するPageRangeのPage番号の配列 → 1,2
assertEquals(new int[]{1,2}, rbFirstPage.getCurrentPageRangePageNumberArray());

// 前のPageRangeがあるか否か → 1Page目より前はないのでFalse
assertFalse(rbFirstPage.isExistPrePageRange());

// 次のPageRangeがあるか否か → 3Page目があるのでTrue
assertTrue(rbFirstPage.isExistNextPageRange());

...(略:http://dbflute.sandbox.seasar.org/ja/tips-paging.html)
- - - - - - - - -/

{PageGroup}

ex) 「ある限られたPage番号」は2Page毎のGroupとする場合
※一般的には、5Page/10Pageとかが基本です。(例は総Page数が少ないので2Page毎のGroupとします)
※これらは、設定されたPageGroupSizeとPaging結果を基に都度算出します。
/- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// **********************
// 「1」Page目のPageGroup
// **********************
// PageGroupSizeは2Page毎のGroupとする
rbFirstPage.setPageGroupSize(2);

// 該当するPageGroupのPage番号の配列 → 1,2
assertEquals(new int[]{1,2}, rbFirstPage.getCurrentPageGroupPageNumberArray()));

// 前のPageGroupがあるか否か → 1Page目より前はないのでFalse
assertFalse(rbFirstPage.isExistPrePageGroup());

// 次のPageGroupがあるか否か → 3Page目があるのでTrue
assertTrue(rbFirstPage.isExistNextPageGroup());

...(略:http://dbflute.sandbox.seasar.org/ja/tips-paging.html)
- - - - - - - - -/


外だしSQLでもPagingはもちろん可能です。
詳しくは http://dbflute.sandbox.seasar.org/ja/tips-paging.html をご覧下さい。


DBFluteはできるだけ現場の悩みを解決することに重点を置きたいと考えております。