検索条件のカスタマイズ
最終更新日: 2021年12月14日
R8 | R9
「クライテリア」は、Wagby内部で利用している、検索条件を管理するクラスです。SQL に相当する表現能力があり、利用するデータベースに依存しないことや、コンパイル時に型をチェックしエラーを検出できるといったメリットがあります。
図1にあるように、ユーザが入力した「検索条件」は、Webフォームから「コンディションモデル」という形で Wagby に取り込まれます。コンディションモデルはさらに「クライテリア」に変換されます。このクライテリアが SQL に変換され、データベースへの問い合わせを行います。
Wagby の標準では、複数項目の検索条件はすべて AND 結合となります。例えば、顧客モデル(customer) の mainstaff 項目が "花子" または substaff 項目が "花子" という検索は、標準機能では実現できません。(標準機能では、mainstaff が "花子" かつ substaff も "花子" という AND 結合になります。)
クライテリアをカスタマイズすることで、複数項目の OR 検索を実現できます。
検索フォームで指定された担当者項目の検索条件値を主担当者、副担当者との OR 検索とする例を考えます。
具体的には、顧客モデル(customer) の mainstaff 項目が "ジャスミン花子" または substaff 項目が "ジャスミン花子" という検索を実現できるようにします。
「画面 > スクリプト > ヘルパ > 検索」を用意します。
上記スクリプトで (*1) の処理を行わないと、次の SQL が実行されてしまいます。
WHERE 句の最初の mainstaff LIKE... は自動生成コードが付与したものですが、この要件では不要です。そのため、元の検索条件を null で上書きして、この SQL が生成されないようにします。コンディションモデルからクライテリアに変換されたとき、内部では criteria.like(meta.mainstaff, null) というコードと解釈されますが、第二引数が null の criteria は無視されるため期待どおりの動作となります。
項目 item1 に対して次のような検索を行う要件を想定します。
この場合、配列 ['1','2','3'] を事前に用意し、この配列を引数に渡してください。配列が渡された場合、内部で OR 扱いとします。
チェックボックス型の項目 item1 に、検索条件の初期値として "OR 1 2 3" という文字列がセットされていたとします。
この文字列を解釈し、文字配列にして検索条件とするスクリプトの例を示します。
クライテリアの定義方法について、具体的なコード例で説明します。
$r では次の関数が用意されています。
これらを $r.or() や $r.and() でつなげていくことになります。
Criteria プログラミングで ORDER BY 句を実現することができます。ここでは model1 モデルの item1, item2 項目でソートする例を示します。
このスクリプトの後に Wagby 標準の ORDER BY が追加されますが、スクリプト内で指定しておくことで標準の ORDER BY よりも優先されるので、意図した順に並べることができます。
クライテリア
クライテリアをカスタマイズするメリット
例 OR検索 [1]
要件
用意するスクリプト
// customerモデルを定義すると CustomerMeta クラスは自動生成されます。
var meta = new Packages.jp.jasminesoft.wagby.model.customer.CustomerMeta();
// スクリプトでは criteria.like() 等を利用すると
// Can't unambiguously select between fixed arity signatures
// エラーが発生することがあるため、$r を使って検索条件を組み立てます。
// criteria のメソッドは add() のみを使って下さい。
var $r = criteria.restrictions();
// "mainstaff" like '%ジャスミン花子%' OR "substaff" like '%ジャスミン花子%'
criteria.add(
$r.or(
$r.like(meta.mainstaff, customer_c.mainstaff),
$r.like(meta.substaff, customer_c.mainstaff)
)
);
customer_c.mainstaff = null; // 元の検索条件は消去しておく。(*1)
元の検索条件を消去する
WHERE
mainstaff LIKE ‘%ジャスミン花子%’
AND (
mainstaff LIKE ‘%ジャスミン花子%’
OR substaff LIKE ‘%ジャスミン花子%’
)
AND...
例 OR検索 [2]
item1='1' or item1='2' or item1='3'...
チェックボックスへの OR 検索
var item1 = model1_c.item1;
if (item1 !== null) {
if (item1.startsWith("OR ")) {
item1 = item1.substring(2);// 先頭の "OR " を除き、空白区切りの文字列を配列にする。
var array = item1.split(/\s/);
//for (i = 0; i < array.length; i++) {
// print(array[i]);
//}
var meta = new Packages.jp.jasminesoft.wagby.model.model1.Model1Meta();
var $r = criteria.restrictions();
criteria.add(
$r.eq(meta.item1, array)
);
model1_c.item1 = null;// 元々の検索値 "OR 1 2 3" 文字列を消去する。
}
}
クライテリアの詳細
// criteria.add() を使うと AND で検索条件が追加されます。
// WHERE "mainstaff" LIKE '%花子%' AND "substaff" LIKE '%花子%'
criteria.add($r.like(meta.mainstaff, "花子"));
criteria.add($r.like(meta.substaff, "花子"));
// $r.and() でも同様に AND で検索条件が追加されます。
// 次の記述方法でも同じ SQL が生成されます。
// WHERE "mainstaff" LIKE '%花子%' AND "substaff" LIKE '%花子%'
criteria.add(
$r.and(
$r.like(meta.mainstaff, "花子"),
$r.like(meta.substaff, "花子")
)
);
// $r.like(), $r.and() の戻り値を変数に格納することも可能です。
// 次の記述方法でも同じ SQL が生成されます。
// WHERE "mainstaff" LIKE '%花子%' AND "substaff" LIKE '%花子%'
var likeCriterion01 = $r.like(meta.mainstaff, "花子");
var likeCriterion02 = $r.like(meta.substaff, "花子");
var andCriterion = $r.and(likeCriterion01, likeCriterion02);
criteria.add(andCriterion);
// $r.or() を使うことで OR 検索を行うことができます。
// WHERE "mainstaff" LIKE '%花子%' OR "substaff" LIKE '%花子%'
criteria.add(
$r.or(
$r.like(meta.mainstaff, "花子"),
$r.like(meta.substaff, "花子")
)
);
// 引数が null の場合はその条件は無視されます。
// WHERE "substaff" LIKE '%花子%'
criteria.add(
$r.or(
$r.like(meta.mainstaff, null),
$r.like(meta.substaff, "花子")
)
);
// 単一項目への OR 検索は引数を追加するだけで実現可能です。
// WHERE "mainstaff" LIKE '%花子%' OR "mainstaff" LIKE '%太郎%' OR "mainstaff" LIKE '%次郎%'
criteria.add($r.like(meta.mainstaff, "花子", "太郎", "次郎"));
// 複雑な検索条件。
// "住所が「沖縄」のお客様で、かつ、主担当が「花子」
// または、
// 住所が「北海道」のお客様で、かつ、主担当が「次郎」"
// となっている顧客データを抽出する。
// WHERE (("address" LIKE '%沖縄%' AND "mainstaff" LIKE '%花子%') OR ("address" LIKE '%北海道%' AND "mainstaff" LIKE '%次郎%' ))
criteria.add(
$r.or(
$r.and(
$r.like(meta.address, "沖縄"),
$r.like(meta.mainstaff, "花子")
),
$r.and(
$r.like(meta.address, "北海道"),
$r.like(meta.mainstaff, "次郎")
)
)
);
利用できる検索条件
提供されるメソッド 説明 コードの記述方法
eq 等しい eq(meta, values) ne 等しくない ne(meta, values) like 文字列の部分一致 like(meta, values) likePrefix 文字列の前方一致 likePrefix(meta, values) likeSuffix 文字列の後方一致 likeSuffix(meta, values) ge 以上 ge(meta, value) gt より大きい gt(meta, value) le 以下 le(meta, value) lt より小さい lt(meta, value) between 範囲検索 between(meta, lowValue, highValue) isNull nullかどうか isNull(meta) isNotNull nullでないかどうか isNotNull(meta) ソートの指定
// ORDER BY item1 DESC, item2 ASC を指定する。
var Order = Java.type("org.hibernate.criterion.Order");
var meta = new Packages.jp.jasminesoft.wagby.model.model1.Model1Meta();
criteria.addOrder(Order.desc(meta.item1.name()))
// 続けて追加すれば複数指定することも可能。
criteria.addOrder(Order.asc(meta.item2.name()))
仕様・制約