(外だしSQL)selectList()

"外だしSQLの使い方" を既に読んでいることが前提となります。

概要

外だしSQLでリスト検索 をします。

会話上では、(外だしSQLの)せれくとりすと と表現します。

実装方法

メソッドの呼び出し

outsideSql() の後、selectList() を呼び出します。

e.g. 外だしSQLの一件検索の実装手順 (Eclipseでコード補完) @Java
memberBhv.o // .o と打って enter
--
memberBhv.outsideSql().s // .s と打って enter
--
memberBhv.outsideSql().selectList(path, pmb, entityType);
// あらかじめ補完される引数の名前に合わせておくとスムーズに

メソッドはオーバーロードで "定型呼び出し形式" と "フリースタイル形式" と二つあります。

定型呼び出し形式

TypedParameterBean を引数に受け取ります。(null は許可されません)

CustomizeEntityマーク、および、ParameterBeanマークが定義されていることで TypedParameterBean の定型呼び出しが利用できます。

フリースタイル形式

パス、パラメータ(ParameterBean)、戻り値Entityの型の三つの要素を引数に受け取ります。 それぞれフリースタイル形式の基本仕様と全く同じです。

外だしSQLの使い方 - フリースタイル基本仕様

検索結果の受け取り

検索結果は、TypedParameterBean に関連付けられている Entity 型、もしくは、第三引数で指定した Entity 型の ListResultBean を戻り値として受け取ります。

e.g. 外だしSQLの一件検索の実装 @Java
String path = MemberBhv.PATH_selectSimpleMember;
SimpleMemberPmb pmb = new SimpleMemberPmb();
pmb.setMemberId(3);
Class<?> entityType = SimpleMember.class;
ListResultBean<SimpleMember> memberList = 
    memberBhv.outsideSql().selectList(path, pmb, entityType)

リストの型は、ListResultBean となります。java.util.List の実装クラスなので、そのままリストとして利用できます。(java.util.List型で受け取っても問題ありません)

検索結果が存在しない場合

検索結果が存在しない場合の戻り値は空のリストです。null は絶対に戻りません。

スカラ型で受け取る

SQL上の select 句のカラムを一つにして、検索結果を String や Integer などのスカラ値(スカラ型)のリストで受け取ることも可能です。TypedParameterBean ではCustomizeEntityマークに加えて scalar オプションを付与します。

e.g. スカラ型のオプションを指定 {MemberBhv_selectMemberName.sql} @SQL-File
-- #df:entity#
-- +scalar+
select MEMBER_NAME
  from MEMBER
e.g. 文字列のスカラ値のリストを検索 @Java
MemberNamePmb pmb = new MemberNamePmb();
ListResultBean<String> valueList = 
    memberBhv.outsideSql().selectList(pmb)
// select MEMBER_NAME from ... where MEMBER_STATUS_CODE = ...

スカラ値での検索においても、検索結果がない場合の扱いについては全く同じです。

ページングのSQLでリスト検索

大量データ検索の抑制のため?

ページング検索のSQLをリスト検索でも使いたい、というような場合、少し工夫が必要です。

通常、ページング検索のSQLはリスト検索では利用できません。自動生成された TypedParameterBean が ListHandlingPmb インターフェースと関連付かないので、selectList()の引数でコンパイルエラーになるようになっています。

ページング検索を想定しているSQLなのであれば、そのままページング条件なしに検索すると大量データ検索になる可能性があるため、安全のために共有できないようになっています。 業務要件的にも、同じになることはほとんどないだろうという想定です。あるとすれば、リスト検索ではなくカーソル検索を想定しています。ページング検索とカーソル検索は共有できます。 (まずは、カーソル検索の方がマッチするのでは?ということを考えると良いでしょう)

ただ、業務要件的に固定条件が入って大量データ検索にならないことが保証されているような場合であれば、ページング検索のSQLをリスト検索でも使いたくなることはあるかもしれません。

ExクラスにてListHandlingPmbとboolean制御

ManualPagingの外だしSQLのページング条件部分にて、リスト検索時はページング条件が無効になるように isListHandling() の条件分岐を入れます。 (代理判定メソッドの自動判別の機能を使っています)

e.g. ページングのSQLの中に、リスト検索のための条件分岐を指定 @SQL-File
 /*IF pmb.isPaging()*/
 order by PURCHASE_MAX_PRICE desc nulls last, mb.MEMBER_ID asc
 /*IF !pmb.isListHandling()*/
 limit /*pmb.fetchSize*/20 offset /*pmb.pageStartIndex*/80
 /*END*/
 /*END*/
  • ページング条件の制御のために、必ず ManualPaging である必要があります

ParameterBean のExクラスにて、ListHandlingPmbインターフェースをimplementsして、共有のためのboolean制御を行います。 (少し特殊ですので、別の人が見たときに迷わせないようにコメントを書いておきましょう。このドキュメントへのURLを記載しておくと良いです)

e.g. ParameterBean のExクラスにて、ListHandlingPmbとboolean制御 @Java
...
 * @author DBFlute(AutoGenerator)
 * @author jflute
 */
public class PagingWithListMemberPmb extends BsPagingWithListMemberPmb // can select list
        implements ListHandlingPmb<MemberBhv, PagingWithListMember> {

    private boolean listHandling;

    @Override
    public boolean isPaging() { // not to depend on framework default value
        return super.isPaging() || listHandling; // always true if list handling
    }

    @Override
    public boolean isListHandling() { // to suppress paging condition
        return listHandling;
    }

    /**
     * Use parameter-bean for list handling.
     */
    public void forListHandling() {
        listHandling = true;
    }
}
  • ListHandlingPmbのジェネリック型は、Bsクラスと同じものを
  • isPaging()のオーバーライドは必須ではないが、フレームワークのデフォルト値に依存しないように
  • クラスのJavaDocにauthorを付けるポリシーの場合は、ここでも忘れずに

そして、リスト検索を実行するときに(だけ)、forListHandling() メソッドを呼びます。

e.g. リスト検索であることを示して外だしSQLを実行 @Java
PagingWithListMemberPmb pmb = new PagingWithListMemberPmb();
pmb.forListHandling();

ListResultBean<PagingWithListMember> memberList = memberBhv.outsideSql().selectList(pmb);

...

手動による制御なので、ページング検索側のプログラムも含めて、しっかりテストをしましょう。