OrscopeQuery
概要
複数の絞り込み条件を or で連結します。
通常の Query の連結条件は and です。OrscopeQuery を使うことで、ある範囲の複数条件の Query を or 条件にすることができます。
パフォーマンス考慮において、or と union はよく議論されます。特に、大量データのテーブルに対しての検索では、OrscopeQuery はよく吟味してから利用して下さい。
会話上では、おあすこーぷくえり と表現します。
実装方法
実装の流れ ※1.1.x (Java8版)
ConditionBean の orscopeQuery() を呼び出し、引数のコールバック(orQuery)で or 条件の Query を設定します。そのコールバック内で設定された条件同士が or で連結されます。
e.g. OrscopeQuery条件の実装手順 (Eclipseでコード補完) {MEMBER} @Java
cb.or // .or と打って enter
--
// メソッドが補完されて、引数の "orCBLambda" が選択状態に
cb.orscopeQuery(orCBLambda);
--
// cbLambdaの部分で、_ll (補完テンプレートが有効なら)
cb.orscopeQuery(_ll);
--
// 実装メソッドの空実装が自動生成される (Eclipse-3.5 以上)
cb.orscopeQuery(orCB -> {
// 会員名称が "s" で始まる、もしくは、会員IDが 3 の会員
orCB.query().setMemberName_Likesearch("s", op ->: op.likePrefix());
orCB.query().setMemberId_Equal(memberId);
});
e.g. 会員名称が "s"、もしくは、会員IDが 3 の会員 @Displaysql
...
from MEMBER dfloc
where (dfloc.MEMBER_NAME like 's%' escape '|'
or dfloc.MEMBER_ID = 3
)
通常の Query と OrscopeQuery を組み合わせて利用できます。
e.g. 正式会員で、会員名称が "s" で始まる、もしくは、会員IDが 3 の会員 @Java
cb.query().setMemberstatusCode_Equal_Formalized();
cb.orscopeQuery(orCB ->: {
orCB.query().setMemberName_Likesearch("s", op ->: op.likePrefix());
orCB.query().setMemberId_Equal(3);
});
e.g. 正式会員で、かつ、[会員名称が "s" で始まる、もしくは、会員IDが 3] の会員 @Displaysql
...
from MEMBER dfloc
where dfloc.MEMBER_sTATUs_CODE = 'FML'
and (dfloc.MEMBER_NAME like 's%' escape '|'
or dfloc.MEMBER_ID = 3
)
実装の流れ ※1.0.x (Java6版)
ConditionBean の orscopeQuery() を呼び出し、引数のコールバック(orQuery)で or 条件の Query を設定します。そのコールバック内で設定された条件同士が or で連結されます。
e.g. OrscopeQuery条件の実装手順 (Eclipseでコード補完) {MEMBER} @Java
MemberCB cb = new MemberCB();
cb.or // .or と打って enter
--
// メソッドが補完されて、引数の "orQuery" が選択状態に
cb.orscopeQuery(orQuery)
--
// "new " (new + 空白一つ) と打って ctrl + space そして enter
cb.orscopeQuery(new )
--
// 実装メソッドの空実装が自動生成される (Eclipse-3.5 以上)
cb.orscopeQuery(new OrQuery<MemberCB>() {
public void query(MemberCB orCB) {
// TODO Auto-generated method stub
}
})
--
// インナークラスに渡すために final をつける。
// 先にインナークラスの中で参照してから ctrl + 1 で final を補完してもOK。
final Integer memberId = 3;
// ctrl (or command) + D で不要な空行やTODOコメントを消して
// or 条件の絞り込み条件を指定
cb.orscopeQuery(new OrQuery<MemberCB>() {
public void query(MemberCB orCB) {
// 会員名称が "s" もしくは "J" で始まる、もしくは、会員IDが 3 の会員
orCB.query().setMemberName_Prefixsearch("s");
orCB.query().setMemberName_Prefixsearch("J");
orCB.query().setMemberId_Equal(memberId);
}
}); // セミコロンを忘れずに
or 条件の中の and 条件
or 条件の中で and 条件を利用することができます。これを OrscopeQuery の AndPart と呼びます。OrscopeQuery の中のコールバックの中で、orscopeQueryAndPart() を呼び出し、引数のコールバックの中で and 条件にしたい絞り込み条件を設定します。@since 0.9.7.3
e.g. 退会会員、もしくは、正式会員日時のなく会員IDが100以上、もしくは、生年月日のない正式会員 @Java
MemberCB cb = new MemberCB();
cb.orscopeQuery(orCB -> {
orCB.query().setMemberstatusCode_Equal_Withdrawal();
orCB.orscopeQueryAndPart(andCB -> {
andCB.query().setMemberId_GreaterEqual(100);
andCB.query().setFormalizedDatetime_IsNull();
});
orCB.orscopeQueryAndPart(andCB -> {
andCB.query().setMemberstatusCode_Equal_Formalized();
andCB.query().setBirthdate_IsNull();
});
});
e.g. 退会会員、もしくは、正式会員日時のなく会員IDが100以上、もしくは、生年月日のない正式会員 @Displaysql
...
from MEMBER dfloc
where (dfloc.MEMBER_sTATUs_CODE = 'WDL'
or (dfloc.MEMBER_ID >= 100 and dfloc.FORMALIZED_DATETIME is null)
or (dfloc.MEMBER_sTATUs_CODE = 'FML' and dfloc.BIRTHDATE is null)
)
OrscopeQuery を経由しない AndPart、および、AndPart 内での OrscopeQuery の呼び出しは利用できません。 (ネストした OrscopeQuery はサポートされていません)
Likesearch の splitBy
Likesearch の splitBy は、それ自身で and か or を選択できる特殊な機能です。OrscopeQuery 内で使った場合でも(AndPart も含む)、連結条件は splitBy の仕様を優先します。
e.g. 会員名称に "s" と "t" が含まれている、もしくは、"J" で始まる会員 @Java
MemberCB cb = new MemberCB();
cb.orscopeQuery(new OrQuery<MemberCB>() {
public void query(MemberCB orCB) {
LikesearchOption option
= new LikesearchOption().likeContain().splitByspace();
orCB.query().setMemberName_Likesearch("s t", option);
orCB.query().setMemberName_Prefixsearch("J");
}
});
e.g. 会員名称に "s" もしくは "M" で始まる、もしくは、"J" で始まる会員 @Displaysql
...
from MEMBER dfloc
where ((dfloc.MEMBER_NAME like '%s%' escape '|' and dfloc.MEMBER_NAME like '%t%' escape '|')
or dfloc.MEMBER_NAME like 'J%' escape '|'
)
e.g. 会員名称に "s" もしくは "M" で始まる、もしくは、"J" で始まる会員 @Java
MemberCB cb = new MemberCB();
cb.orscopeQuery(new OrQuery<MemberCB>() {
public void query(MemberCB orCB) {
LikesearchOption option
= new LikesearchOption().likePrefix().splitByspace().asOrsplit();
orCB.query().setMemberName_Likesearch("s M", option);
orCB.query().setMemberName_Prefixsearch("J");
}
});
e.g. 会員名称に "s" もしくは "M" で始まる、もしくは、"J" で始まる会員 @Displaysql
...
from MEMBER dfloc
where (dfloc.MEMBER_NAME like 's%' escape '|'
or dfloc.MEMBER_NAME like 'M%' escape '|'
or dfloc.MEMBER_NAME like 'J%' escape '|'
)
そもそも AsOrsplit は、内部的に OrscopeQuery を利用して実現しています。
日付のFromTo (DateFromTo)
OrscopeQuery の中で日付の FromTo (DateFromTo) 条件を利用した場合は、FromTo 条件は and 固定で連結されます。(and で利用することに意味がある機能のため) @since 0.9.9.4A
メソッド仕様
コールバックでは絞り込み条件のみ
OrscopeQuery 内では、絞り込み条件のみ設定できます。以下の機能が利用できます。
- query() 経由で利用できる絞り込み条件
- OnClause, InlineView
- ColumnQuery
※setupselect や UnionQuery など、それ以外の機能を呼び出してはいけません。
条件が一つだけの場合
業務的には、Query を使って設定したときと同じ動きになります。sQL上では、その唯一の条件が OrscopeQuery の名残である括弧で囲まれます。
条件が全て無効になった場合
例えば、OrscopeQuery 内の条件値が全て null で条件が成立しなかった場合、 OrscopeQuery を呼び出さなかったのと同じ動きになります。
同カラム同条件に対する複数指定は有効に
通常の Query では、絞り込み条件の同カラムに対する複数指定は、ConditionKey 次第では上書きになりますが、OrscopeQuery 内では(AndPart も含む)、呼び出した分だけ条件が付与されます。
e.g. 会員IDが 1 もしくは 3 の会員 @Java
cb.orscopeQuery(orCB -> {
orCB.query().setMemberId_Equal(1);
orCB.query().setMemberId_Equal(3);
});
e.g. 会員IDが 1 もしくは 3 の会員 @Displaysql
...
from MEMBER dfloc
where (dfloc.MEMBER_ID = 1
or dfloc.MEMBER_ID = 3
)
但し、同カラムに対する同じ条件値での複数指定(業務的に無意味な条件)も、呼び出した分だけ条件が付与されてしまいます。 (通常の Query では、その旨を伝えるデバッグログが出力されて無視される)
サブクエリのCBは独立
OrscopeQuery の中で ExistsReferrer などのサブクエリを利用する場合に、サブクエリ内の ConditionBean の連結条件に特に変わりはありません。OrscopeQuery の状態が引き継がれることはありませんので、サブクエリの中で OrscopeQuery を利用する場合は、明示的に呼び出して設定します。
無効な呼び出し
以下のような呼び出しは無効です。
- OrscopeQuery 内でない場所での AndPart の呼び出し (業務的に無意味)
- AndPart 内での (ネストした)OrscopeQuery の呼び出し (サポートされない)
ソースコードリーディングのススメ
OrscopeQuery は、ConditionBean の中で最も実現が大変だった機能の一つです。