はじめに
今回は、
ページング検索
ページング検索とは?
まずは基本的な概念から説明します。
ここで言うページング検索とは、

そして、
1. ページングなし件数取得
→ ページングをしなかった場合の件数を取得し、総ページ数などの導出要素とする。
→ ページング検索画面のページングナビゲーションの実装において必須の処理となる。
2. ページング実データ検索
→ ページング絞りの条件で絞られた取得したい実データのリスト検索。
3. ページング結果計算処理
→ ページングナビゲーションンで利用するページング結果の計算処理。(総ページ数の導出や次ページ有無判定など)
→ ページング検索画面のページングナビゲーションの実装において必須の処理となる。
ポイントは、
仕組みによってはここでWhere句の条件が二箇所にわたる冗長管理に
なってしまったりと、
ConditionBeanによるページング検索
では、
普通の検索
まずは普通の検索を見て下さい。
// 取得:会員スタータスを結合して取得
// 条件:会員アカウントが'S'で始まること
// 並び:会員IDの昇順
MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query().setMemberAccount_PrefixSearch("S");
cb.query().addOrderBy_MemberId_Asc();
List<Member> memberList = memberBhv.selectList(cb);
for (Member member : memberList) {
...
}
ページング検索
そして、
ConditionBeanによるページング検索は以下のようになります。
// 取得:会員スタータスを結合して取得
// 条件:会員アカウントが'S'で始まること
// 並び:会員IDの昇順
MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query().setMemberAccount_PrefixSearch("S");
cb.query().addOrderBy_MemberId_Asc();
// 1ページ20件で3ページ目を検索
cb.paging(20, 3);//
// ページング検索
// 1. ページングなし件数取得
// 2. ページング実データ検索
// 3. ページング結果計算処理
PagingResultBean<Member> memberPage = memberBhv.selectPage(cb);
for (Member member : memberPage) {
...
}
paging()にて
実は、
PagingResultBean<Member> memberPage = memberBhv.selectPage(cb);
// 3ページ目(41件目から60件目)のリスト
for (Member member : memberPage) {
...
}
// ページングなし条件での総件数
int allRecordCount = memberPage.getAllRecordCount();
// 総ページ数
int allPageCount = memberPage.getAllPageCount();
// 対象ページ番号
int currentPageNumber = memberPage.getCurrentPageNumber();
// 前ページがあるか否か
boolean isExistPrePage = memberPage.isExistPrePage();
// 次ページがあるか否か
boolean isExistNextPage = memberPage.isExistNextPage();
// ナビゲーションのページリンク候補一覧
memberPage.setPageRangeSize(5);
List<Integer> pageNumberList = memberPage.pageRange().createPageNumberList();
// ...その他省略
「総ページ数」

ページングナビゲーションで必要な情報の計算処理はDBFluteが行います。
そのため、
ページング絞込みのSQL
ページングの絞込みは、
関連補足:最初のn件を取得
「最初のn件を取得する」
// 取得:会員スタータスを結合して取得
// 条件:会員アカウントが'S'で始まること
// 並び:会員IDの昇順
MemberCB cb = new MemberCB();
cb.setupSelect_MemberStatus();
cb.query().setMemberAccount_PrefixSearch("S");
cb.query().addOrderBy_MemberId_Asc();
// 最初の20件
cb.fetchFirst(20);
// 検索結果の最初の20件だけを取得
List<Member> memberList = memberBhv.selectList(cb);
for (Member member : memberList) {
...
}
OutsideSql(外だしSQL)によるページング検索
それでは、
Auto/Manual (ConditionBeanとの違い)
ConditionBeanとは違う大きなポイントをまず説明します。
こちらの場合は、
- AutoPaging : ResultSetレベルでの自動絞り込み
- ManualPaging : SQLレベルでの手動絞込み(自分で書く)
例えば、
「ResultSetレベルでの自動絞り込み」
普通の検索
まずは、
-- #SimpleMember#
-- !SimpleMemberPmb!
-- !!Integer memberId!!
-- !!String memberName!!
select member.MEMBER_ID
, member.MEMBER_NAME
, memberStatus.MEMBER_STATUS_NAME
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
/*BEGIN*/where
/*IF pmb.memberId != null*/member.MEMBER_ID = /*pmb.memberId*/3/*END*/
/*IF pmb.memberName != null*/and member.MEMBER_NAME like /*pmb.memberName*/'ス' || '%'/*END*/
/*END*/
order by member.MEMBER_ID asc
// SQLのパス
String path = MemberBhv.PATH_selectSimpleMember;
// 検索条件
SimpleMemberPmb pmb = new SimpleMemberPmb();
pmb.setMemberName("ス");
// 戻り値Entityの型
Class<SimpleMember> entityType = SimpleMember.class;
// ## Act ##
// SQL実行!
List<SimpleMember> memberList = memberBhv.outsideSql().selectList(path, pmb, entityType);
for (Member member : memberList) {
...
}
ページング検索 (AutoPaging)
そして、
-- #SimpleMember#
-- !SimpleMemberPmb extends SPB!
-- !!Integer memberId!!
-- !!String memberName!!
/*IF pmb.isPaging()*/
select member.MEMBER_ID
, member.MEMBER_NAME
, memberStatus.MEMBER_STATUS_NAME
-- ELSE select count(*)
/*END*/
from MEMBER member
/*IF pmb.isPaging()*/
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
/*END*/
/*BEGIN*/where
/*IF pmb.memberId != null*/member.MEMBER_ID = /*pmb.memberId*/3/*END*/
/*IF pmb.memberName != null*/and member.MEMBER_NAME like /*pmb.memberName*/'ス' || '%'/*END*/
/*END*/
/*IF pmb.isPaging()*/
order by member.MEMBER_ID asc
/*END*/
普通の検索と違うところが二点あります。
- 1.
- ParameterBeanの指定に
「extends SPB」 という宣言が追加されています。 - これは生成するParameterBeanが
「SimplePagingBean」 というクラスを継承することを示し、 ページング絞りのための情報を扱うことのできるParameterBeanが生成されます。 - 2.
- Select句、
Join句、 OrderBy句が 「/*IF pmb. isPaging()*/」 にて囲われています。 - このif文は、
「ページングなし件数取得」 と 「ページング実データ検索」 を区別しています。 - DBFluteでは、
ページングのSQLを 「ページングなし件数取得」 と 「ページング実データ検索」 とで分ける必要はありません。このような形で共存させることによって、 一番変わりやすいWhere句の条件を両方の処理にて再利用しています。 - 先述の
「extends SPB」 の宣言をすることによって、 isPaging()が利用可能になります。
それでは実装を見てましょう。
やりたいことはConditionBeanと変わりません。
「1ページは何件か?
// SQLのパス
String path = "selectUnpaidSummaryMember";
// 検索条件
UnpaidSummaryMemberPmb pmb = new UnpaidSummaryMemberPmb();
pmb.setMemberStatusCode_Formalized();
// 戻り値Entityの型
Class<UnpaidSummaryMember> entityType = UnpaidSummaryMember.class;
// 1ページ20件で3ページ目を検索
pmb.paging(20, 3);
// ## Act ##
// SQL実行!
PagingResultBean<SimpleMember> memberPage
= memberBhv.outsideSql().autoPaging().selectPage(path, pmb, entityType);
// 3ページ目(41件目から60件目)のリスト
for (Member member : memberPage) {
...
}
このように
ページング検索 (ManualPaging)
おおよその流れはAutoPagingで学びました。
ManualPagingは、
...(略)
/*IF pmb.isPaging()*/
order by member.MEMBER_ID asc
/*END*/
/*IF pmb.isPaging()*/
limit /*$pmb.fetchSize*/20, offset /*$pmb.pageStartIndex*/80
/*END*/
「ページング実データ検索」
select *
from (
select base.*, rownum as rn
from (
select ... from ... where ... order by ..
) base
)
where rn > /*$pmb.pageStartIndex*/80
and rn <= /*$pmb.pageEndIndex*/100
そして、
...(略)
// ## Act ##
// SQL実行!
PagingResultBean<SimpleMember> memberPage
= memberBhv.outsideSql().manualPaging().selectPage(path, pmb, entityType);
まとめ
ページング検索をみてみました。 こちらも実務で非常に役に立つ機能です。ぜひ利用してみて下さい。
さて、
- DBFluteBasicExample
- SVN : https://
www. seasar. org/ svn/ sandbox/ dbflute/
Project : trunk/dbflute-basic-example DBFluteの一番基本となるExampleでBehaviorやConditionBeanなどの 使い方を一つ一つ
「JUnitの単体テスト」 の形式で実装して紹介しています。 組み込みデータベース 「H2」 を利用しているため、 SVNからチェックアウト するだけで、 それらテストケースを実行して試すことが可能です。 環境的な面・ 実装的な面両方で参考になるExampleです。 - DBFluteNBasicExample
- SVN : https://
www. seasar. org/ svn/ sandbox/ dbflute/
Project : trunk/dbflute-nbasic-example 実はDBFluteはC#版も用意されています。 そのC#版DBFluteを使ったExampleです。 C#ユーザの方はぜひご覧になられて下さい。
- DBFluteSpringExample
- SVN:https://
www. seasar. org/ svn/ sandbox/ dbflute/
Project : trunk/dbflute-spring-example 実はDBFluteはSpring Frameworkでも動作します。 SpringでDBアクセス周りに困っている方はぜひご覧になられて下さい。
それでは、