外だしSQLの曖昧検索
外だしSQLでもConditionBeanで利用しているLikeSearchOptionが利用可能です。
LikeSearchOptionを利用しなくても曖昧検索は可能ですが、一致の方向(前方、中間、後方)を動的に決定したり、
エスケープ処理を施したりする場合には、LikeSearchOptionはとても有効です。
前提
LikeSearchOptionなしでの実装方法
SQL上にて、「||」演算子や「+」演算子を利用して、ワイルドカードを固定で書きます。
where MEMBER_NAME like /*pmb.memberName*/'テスト値' || '%'
アプリケーションで指定された条件値に対して、SQL実行時にDB側でワイルドカードが付与されて曖昧検索となります。LikeSearchOptionなしだと...
LikeSearchOptionなしでの実装のデメリットとしては、曖昧検索の一致の方向(前方、中間、後方)が固定になってしまうということです。
もし、一致の方向を動的に決定するような要件があった場合はこの方法は利用できません(画面で選択するなど)。
アプリケーション側でワイルドカードを付与することになるでしょう。
また、ワイルドカードのエスケープ処理を入れる場合は、以下のようになりますが:
where MEMBER_NAME like /*pmb.memberName*/'テスト値' || '%' escape '|'
エスケープするには、実際の条件値の中に含まれているワイルドカードにエスケープ文字を付与する必要があります。アプリケーション側で条件値の文字列置換をすることになるでしょう。
エスケープすることを2箇所で意識することになりますし、エスケープ文字の定義も2箇所に飛び火します。
無論、要件的に「一致の方向は固定」・「エスケープはしない」というのであればこの方法で全然問題ありません。
LikeSearchOption利用での実装方法
ConditionBeanで利用しているLikeSearchOptionをそのまま利用することが可能です。
まず、ParameterBeanの宣言にて、該当のプロパティに「:like」という「Likeオプション」を指定します。
(ParameterBeanの「Likeオプション」についてはこちら)
そして、ワイルドカードはテスト値に含めます。(アプリケーション実行時に内部的に付与されるため)
ex) 会員名称プロパティにLikeオプションを指定
-- #OptionMember#
-- !OptionMemberPmb!
-- !!Integer memberId!!
-- !!String memberName:like!!
select member.MEMBER_ID
, member.MEMBER_NAME
, memberStatus.MEMBER_STATUS_NAME
/*END*/
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
/*BEGIN*/where
/*IF pmb.memberId != null*/member.MEMBER_ID = /*pmb.memberId*/3/*END*/
/*IF pmb.memberName != null*/and member.MEMBER_NAME like /*pmb.memberName*/'ス%'/*END*/
/*END*/
/*END*/
order by member.MEMBER_ID asc
その後、Sql2Entityを実行すると、該当プロパティのSetterの第2引数にてLikeSearchOptionが指定できるようになります。
ex) 会員名称「ストイコ100%ビッチ_その」で始まり、かつ、「%」・「_」をパイプライン「|」でエスケープする
final OptionMemberPmb pmb = new OptionMemberPmb();
pmb.setMemberName("ストイコ100%ビッチ_その", new LikeSearchOption().likePrefix().escapeByPipeLine());
final List<OptionMember> resultList = memberBhv.outsideSql().selectList(path, pmb, entityType);
実行するとLikeSearchOptionで指定された通りに曖昧検索されます。
エスケープの面倒な処理などは全てLikeSearchOptionが解決しています。
ex) 実行ログ一部抜粋
(S2DaoInterceptor#traceMethod():201) - /===============================================================================
(S2DaoInterceptor#traceMethod():202) - OutsideSqlDao.selectList()
(S2DaoInterceptor#traceMethod():203) - =========================/
(S2DaoInterceptor#traceMethod():211) - OutsideSql: sql/member/selectOptionMember.sql
(S2DaoInterceptor#traceSqlCommand():444) - SqlCommand Initialization Cost: [00m00s875ms]
(Logger#debug():105) - -- #OptionMember#
-- !OptionMemberPmb!
-- !!Integer memberId!!
-- !!String memberName:like!!
select member.MEMBER_ID
, member.MEMBER_NAME
, memberStatus.MEMBER_STATUS_NAME
from MEMBER member
left outer join MEMBER_STATUS memberStatus
on member.MEMBER_STATUS_CODE = memberStatus.MEMBER_STATUS_CODE
where
member.MEMBER_NAME like 'ストイコ100|%ビッチ|_その%' escape '|'
order by member.MEMBER_ID asc
(S2DaoInterceptor#traceReturn():479) - ===========/ [00m01s422ms - Selected list: 2 first={1,ストイコ100%ビッチ_その1,正式会員}]
但し、ConditionBeanで使っているLikeSearchOptionの機能が全て使えるわけではないのでご注意下さい。例えば、splitByXxx()メソッドはご利用できません。
