はじめに
今回からは、とうとう応用編です。
ConditionBean/OutsideSql(外だしSQL)両方における
「エスケープ付き曖昧検索」を見て行きます。
エスケープ付き曖昧検索
エスケープ付き曖昧検索とは?
まずは基本的な概念から説明します。
曖昧検索は、条件値に含まれているワイルドカード(%や_)を使って、
前方一致・中間一致等を実現します。例えば、条件値が'ス%'であれば
「スで始まるもの」、'%ス%'であれば「スを含むもの」という検索に
なります。しかし、もしデータベース上に「100%ジュースの飲み物」という文字が
格納されていて、「'100%ジュース'を含むもの」という検索をしたい場合に、
条件値が'%100%ジュース%'では正確な検索をすることができません。
なにがまずいかというと、もしデータベース上に「100回回ってから飲むジュース」
というデータが入ってたら、このデータも検索対象になってしまうのです。
「'100%ジュース'を含むもの」という条件からは外れたデータです。
つまりは、ワイルドカード(%や_)も通常の文字として扱いたいこともあるのです。
SQLでは、文字として扱いたい'%'や'_'がある場合に、それらを条件値の中でエスケープします。
そのときエスケープ文字を明示的に指定します。
こうすることで、エスケープ文字でエスケープされた'%'や'_'はワイルドカードではなく、
通常の文字として扱われます。エスケープ文字をエスケープすることも可能です。
この処理は、実業務において結構忘れられがちです。
それは、やらなくても支障のない場合も多いからです。
しかし、全く考慮せずに実装すると思わぬところでトラブることもあります。
商品の品番など複雑なコード体系では、'%'や'_'がコード上に存在することも
あります。その場合に、「検索で余計なデータもたくさんでてきて、探せないんだけど」
とユーザに怒られてしまうこともあります。また、主に前方一致検索を想定している
検索で、先頭に'%'を入れられて中間一致検索になってしまい、インデックスが利用されずに
SQLが全然帰ってこないという事態が発生する可能性もあります
(前方一致にする理由としてインデックスを利用したいからって場合もあるのです)。
「第3回 ConditionBeanで色々な条件組み立て」で紹介したConditionBeanの
PrefixSearchでは、実はエスケープ処理が施されません(簡易な前方一致)。
エスケープをする必要のないケースもたくさんあるので、大抵はこれでも
よいのですが、上記のようなシビアな検索の場合にどうしたら良いのか、
DBFluteの高機能曖昧検索「LikeSearch」をご紹介致します。
ConditionBeanのLikeSearch
ConditionBeanのLikeSearchの基本的な使い方を説明します。
query()メソッドの後、PrefixSearchではなくLikeSearchを選びます。
そのとき、第二引数が必須です。LikeSearchOptionというクラスを生成して、
likePrefix()というメソッドを呼び出すことで前方一致になります。
likePrefix()の部分をlikeContain()やlikeSuffix()にすることで中間一致や後方一致に
することも可能です。
それでは、本題のエスケープ処理です。
このLikeSearchOptionにescapeBy[エスケープ文字]()というメソッドが幾つか存在します。
それを呼び出すことでエスケープ処理が可能になります。
見事に'%'や'_'がエスケープされています。
このエスケープ処理を手動で行い場合に一番間違え易く忘れ易いのが、
「条件値にエスケープ文字を埋め込む作業」です。本当のワイルドカードを
付ける前に文字列置換でエスケープ文字を埋め込む必要があるのですが、
DBFluteはこれを内部的に自動で行います。よって、非常に「安全に」
エスケープ付き曖昧検索を実現することが可能です。
どのエスケープ文字でエスケープするかは、ご利用のデータベースが採用している
エスケープ文字を選んで下さい。(データベース固有の仕様をご確認下さい)
条件値にエスケープ文字が格納されていたらどうしよう!?と考える必要はありません。
条件値内のエスケープ文字も内部的に自動でエスケープされます。
OutsideSql(外だしSQL)のLikeSearch
それでは、今度はOutsideSql(外だしSQL)におけるLikeSearchを見て行きましょう。
こちらに関しては、やろうと思えばエスケープ文字の指定をSQLにベタに
書くことはとても簡単です。SQLに「escape '|'」と自分で書いてしまえば
良いのです。しかし、条件値のエスケープ文字の埋め込み処理は自前で
やる必要がありますし、また、エスケープ文字の指定がSQLとプログラムで
冗長化します。
DBFluteでは、ParameterBeanにLikeSearchOptionを
指定することでConditionBeanのときのようなエスケープ処理の自動化を提供しています。
ParameterBeanの宣言時に、曖昧検索対象のプロパティに「:like」というオプションを
付けてあげて、Sql2Entityを実行します。
すると、ParameterBeanのSetterメソッドにて、LikeSearchOptionが指定できるようになります。
まとめ
エスケープ付き曖昧検索を徹底してみてみました。
実務でぜひ利用してみて下さい。
次回は、とうとう「ページング検索」をみていきます!