DBFlute -- OutsideSqlでのページング検索の基本


ページング検索の「ページング無し件数検索」・「ページング実データ検索」
の2つの処理を1つのSQLで実現するやり方を紹介します。



【Sql2Entityの指定】
# -- #UnpaidSummaryMember#
#
# -- !UnpaidSummaryMemberPmb extends SPB!
# -- !!Integer memberId!!
# -- !!String memberName!!
# -- !!String memberStatusCode!!
# -- !!boolean unpaidMemberOnly!!

ページングをしますので、ParameterBeanに「extends SPB」を付与します。



SQL文中の分岐】
# /*IF pmb.isPaging()*/
# select member.MEMBER_ID
# , member.MEMBER_NAME
# , (select sum(purchase.PURCHASE_PRICE)
# from PURCHASE purchase
# where purchase.MEMBER_ID = member.MEMBER_ID
# and purchase.PAYMENT_COMPLETE_FLG = 0
# ) as UNPAID_PRICE_SUMMARY
# , memberStatus.MEMBER_STATUS_NAME
# -- ELSE select count(*)
# /*END*/
# from MEMBER member
# where ...

ここが最大のポイントです。ParameterBean.isPaging()を利用して、
「ページング実データ検索」なのか「ページング無し件数検索」を切り替えます。
(isPaging()メソッドはフレームワークで提供しています)

o isPaging()==true → 「ページング実データ検索」
o isPaging()==false → 「ページング無し件数検索」

その他、「ページング無し件数検索」では不要な「結合・ソート」などを
取得件数に影響しないものを対象にIF文で囲います。
(これは単なるパフォーマンス考慮です)

# ...
# from MEMBER member
# /*IF pmb.isPaging()*/
# left outer join MEMBER_STATUS memberStatus
# on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
# /*END*/
# /*IF pmb.isPaging()*/
# order by UNPAID_PRICE_SUMMARY desc, member.MEMBER_ID asc
# /*END*/

もし、manualPaging(手動ページング)を利用する場合は、
ページング絞込み行を追加してpmb.isPaging()で囲います。
ここの記述方法はDBによっては異なります。(OracleとかDB2とかはつらい...)

# /*IF pmb.isPaging()*/
# limit /*$pmb.pageStartIndex*/80, /*$pmb.fetchSize*/20
# /*END*/



【呼び出しプログラム】
# // SQLのパス
# final String path = "sql/member/selectUnpaidSummaryMember.sql";
#
# // 検索条件
# final UnpaidSummaryMemberPmb pmb = new UnpaidSummaryMemberPmb();
# pmb.setMemberStatusCode(ClassificationDefinition.CODE_MemberStatus_Formalized);
#
# // 戻り値Entityの型
# final Class entityType = UnpaidSummaryMember.class;
#
# // ページング条件の指定
# pmb.fetchFirst(2);// ページサイズ「2」
# pmb.fetchPage(3);// 3ページ目
#
# // SQL実行!
# final PagingResultBean page
# = memberBhv.outsideSql().autoPaging().selectPage(path, pmb, entityType);

ここの例ではautoPaging()を利用しています。
(もし、manualPaging()の場合は、autoPaging()をmanualPaging()に変えます)



【その他注意点】
「/*IF pmb.isPaging()*/」と「-- ELSE select count(*)」の間の行に
別の行コメント「--」を入れると例外になりますのでご注意下さい。
これはS2DaoのSqlParserの制約となります。

# /*IF pmb.isPaging()*/
# select member.MEMBER_ID
# , member.MEMBER_NAME -- ★ここに行コメントはダメ
# , memberStatus.MEMBER_STATUS_NAME
# -- ELSE select count(*)
# /*END*/

結構、何のカラムかを説明するのに入れたくなるので、ご注意下さい。
(真っ先に自分がハマりました...)


【追記:2007/12/19 15:00】
Exampleにて上記のページングのサンプルを実装しました。

// SVNリポジトリ
https://www.seasar.org/svn/sandbox/dbflute/trunk/dbflute-basic-example

MemberBhvTestクラスのtest_outsideSql_select_autoPaging_selectPage_Tx()メソッドです。
ぜひご覧になられて下さい。