サポート > リポジトリ > 検索制御 > [応用] スクリプトで検索条件をカスタマイズする
ja | en

Wagbyが提供する検索条件は内部で「クライテリア」として管理されています。これをスクリプトで制御する方法を説明します。 R7.11

本ページに記載する方法は「スクリプト」を用います。スクリプトの詳細は「業務ロジック」をお読みください。

「クライテリア (Criteria)」は、Wagby内部で利用している、検索条件を管理するクラスです。SQL に相当する表現能力があり、利用するデータベースに依存しないことや、コンパイル時に型をチェックしエラーを検出できるといったメリットがあります。

図1 クライテリアの位置づけ

図1にあるように、ユーザが入力した「検索条件」は、Webフォームから「コンディションモデル」という形で Wagby に取り込まれます。コンディションモデルはさらに「クライテリア」に変換されます。このクライテリアが SQL に変換され、データベースへの問い合わせを行います。

クライテリアは Wagby が同梱している O/R Mapper ミドルウェア Hibernate が提供するものです。クライテリアから SQL への変換は、Hibernate が行います。

クライテリアをカスタマイズするメリット

Wagby の標準では、複数項目の検索条件はすべて AND 結合となります。例えば、顧客モデル(customer) の mainstaff 項目が "花子" または substaff 項目が "花子" という検索は、標準機能では実現できません。(標準機能では、mainstaff が "花子" かつ substaff も "花子" という AND 結合になります。)

クライテリアをカスタマイズすることで、複数項目の OR 検索を実現できます。

要件

検索フォームで指定された担当者項目の検索条件値を主担当者、副担当者との OR 検索とする例を考えます。

図2 要件イメージ

具体的には、顧客モデル(customer) の mainstaff 項目が "ジャスミン花子" または substaff 項目が "ジャスミン花子" という検索を実現できるようにします。

用意するスクリプト

「画面 > スクリプト > ヘルパ > 検索」を用意します。

図3 スクリプトの作成
WEB-INF/script/<モデルID> フォルダに <モデルID>CriteriaConverter_convert.js が生成されます。
function process() {
  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)
}
  • スクリプト内で暗黙オブジェクト criteria を利用できます。最初に criteria.restrictions() の返戻値を $r で受けるようにします。この $r を使って検索条件を組み立てます。
  • 暗黙オブジェクト criteria に対しては add メソッドのみが利用できます。
  • criteria を用いた検索条件の指定では、対象項目名は文字列ではなく、Wagbyが提供するメタクラスを使います。これによってスペルミスによる実行時エラーといった、デバッグしにくい問題を回避します。

元の検索条件を消去する

上記スクリプトで (*1) の処理を行わないと、次の SQL が実行されてしまいます。

WHERE
    mainstaff LIKE ‘%ジャスミン花子%’
AND (
       mainstaff LIKE ‘%ジャスミン花子%’
    OR substaff LIKE ‘%ジャスミン花子%’
)
AND...

WHERE 句の最初の mainstaff LIKE... は自動生成コードが付与したものですが、この要件では不要です。そのため、元の検索条件を null で上書きして、この SQL が生成されないようにします。コンディションモデルからクライテリアに変換されたとき、内部では criteria.like(meta.mainstaff, null) というコードと解釈されますが、第二引数が null の criteria は無視されるため期待どおりの動作となります。

クライテリアの設定方法について、具体的なコード例で説明します。

  // 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, "次郎")
        )
      )
  );

$r では次の関数が用意されています。 これらを, $r.or() や $r.and() でつなげていくことになります。

提供されるメソッド説明コードの記述方法
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)
isNullnullかどうかisNull(meta)
isNotNullnullでないかどうかisNotNull(meta)
1. 引数が value ではなく、values となっている関数は複数の値を指定することが可能です。
2. 複数の値を指定した場合 eq(), like(), likePrefix(), likeSuffix()は OR 条件となり、ne() は AND 条件となります。