SearchCondition
SearchCondition は <左側オペランド> <演算子> <右側オペランド> という形式をとる SQL WHERE 節の定義式を表します。
以下に例を示します。
MyTable.Column1 = 5
MyTable.Column2 LIKE "E%"
MyTable.Column3 = JoinTable.Column1
オペランドは、SQL 関数や副問い合わせのように、さらに複雑化できます。SearchCondition は任意の RelationalExpression オペランドを使用できます。オペランドは、SearchCondition コンストラクタまたはセッターメソッドを使用して指定できます。以下に、具象的な ColumnExpression の実装を示します。
ClassAttribute
|
このクラスは、SQL ステートメントで使用できるクラス属性を表します。イントロスペクション情報は、関連テーブルおよびコラムの決定に使用されます。
|
SQLFunction
|
このクラスは、SQL ステートメント内の SQL 関数を表します。
|
SubSelectExpression
|
このクラスは、SQL ステートメントで使用できる副問い合わせを表します。副問い合わせは、StatementSpec 属性で指定します。
|
ConstantExpression
|
このクラスは、SQL ステートメント内の定数を表します。
|
KeywordExpression
|
このクラスは、SQL ステートメントで使用できる SQL キーワードを求める定義式を表します。
|
RangeExpression
|
このクラスは、SQL WHERE 節の範囲を表します。
|
DateExpression
|
このクラスは、SQL ステートメント内の日付定数を表します。この ConstantExpression のサブクラスは、日付値の特別な処理を実行するために必要です。
|
ArrayExpression
|
このクラスは、SQL IN 節内の定数の配列を表します。
|
TableColumn
|
このクラスは、SQL ステートメントで使用できるテーブルコラムを表します。指定した正確なテーブルおよびコラム名が SQL ステートメントで直接使用されます。
|
|
|
以下の例は、指定日以降の最も古い修正タイムスタンプを持つ WTPartMaster オブジェクトを判断するための複雑な照会です。以下に、この照会の SQL を示します。
SELECT A0.*
FROM WTPartMaster A0
WHERE (A0.modifyStampA2 IN (SELECT MIN(B0.modifyStampA2)
FROM WTPartMaster B0
WHERE B0.modifyStampA2 > ’cutoff’) )
以下のコードで、照会の仕様を作成します。
Class targetClass = wt.part.WTPartMaster.class;
QuerySpec subSelect = new QuerySpec();
subSelect.getFromClause().setAliasPrefix("B");
int subIndex = subSelect.appendClassList(targetClass, false);
int[] fromIndicies = { subIndex };
ClassAttribute subModifyStamp =
new ClassAttribute(targetClass,WTAttributeNameIfc.MODIFY_STAMP_NAME);
SQLFunction minFunction = SQLFunction.new SQLFunction(SQLFunction.
MINIMUM, subModifyStamp);
subSelect.appendSelect(minFunction, fromIndicies, false);
subSelect.appendWhere(new SearchCondition(subModifyStamp,
SearchCondition.GREATER_THAN, DateExpression.newExpression(cutoff)),
fromIndicies);
QuerySpec select = new QuerySpec();
int index = select.appendClassList(targetClass, true);
select.appendWhere(new SearchCondition(modifyStamp,SearchCondition.IN,
new SubSelectExpression(subSelect)), new int[] { index });
複合照会
複合照会は、集合演算子を使用し、複数のコンポーネント照会を単一の SQL ステートメントに結合する SQL ステートメントです。集合演算子には、UNION、UNION ALL、INTERSECT、および MINUS があります。複合照会は、集合演算子を指定し、コンポーネント照会を追加して作成します。コンポーネント照会は StatementSpec オブジェクトなので、複合照会のネストもサポートされます。
以下の例は、特定の PartMaster 番号およびその代替の番号すべてを返す複合照会です。番号のみが選択され、完全なオブジェクトは選択されません。すべてのサブクラスを考慮する場合、複合照会ステートメントにはすべてのサブクラステーブルが含まれるので、このような選択が必要です。これらのサブクラステーブルには、ほかのコンポーネントステートメントとは互換性のないステートメントごとに選択リストを作成する追加のコラムが含まれる場合があります。SQL では、複合ステートメントの各コンポーネント照会が選択リストで同一番号を持ち、対応するタイプであることが必要です。以下に、この照会の SQL を示します。
SELECT A0.number
FROM WTPartMaster A0
WHERE (A0.name = ‘ENGINE')
UNION
SELECT A2.number
FROM WTPartMaster A0,WTPartAlternateLink A1,WTPartMaster A2
WHERE (A0.name = ‘ENGINE') AND
(A0.idA2A2 = A1.idA3A5) AND (A2.idA2A2 = A1.idA3B5)
以下のコードで、照会の仕様を作成します。最初に作成する選択は、ENGINE という名前の PartMasters 用です。
QuerySpec partSelect = new QuerySpec();
int partIndex = partSelect.appendClassList(wt.part.WTPartMaster.class, false);
partSelect.appendWhere(new SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });
次に作成する選択は、返される PartMaster の代替用です。代替は、WTPartAlternateLink クラスを使用して表します。これは、PartMasters 間の多対多の関係です。オリジナルの部品とその代替のこの関係では、結合を指定する必要があります。
QuerySpec altSelect = new QuerySpec();
partIndex = altSelect.appendClassList(wt.part.WTPartMaster.class, false);
int altIndex = altSelect.appendClassList(W wt.part.WTPartAlternateLink.class,
false);
int altPartIndex = altSelect.appendClassList(wt.part.WTPartMaster.class,
false);
altSelect.appendSelect(new ClassAttribute(
wt.part.WTPartMaster.class, wt.part.WTPartMaster.NUMBER),
new int[] { altPartIndex }, false);
altSelect.appendWhere(new
SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });
altSelect.appendJoin(altIndex, wt.part.WTPartAlternateLink.ALTERNATES_ROLE,
partIndex);
altSelect.appendJoin(altIndex, wt.part.WTPartAlternateLink.ALTERNATE_FOR_ROLE,
altPartIndex);
最後に、前の 2 つの照会および UNION 集合演算子を使用して複合ステートメントを作成します。
CompoundQuerySpec compound = new CompoundQuerySpec();
compound.setSetOperator(SetOperator.UNION);
compound.addComponent(partSelect);
compound.addComponent(altSelect);
アクセス制御に関する考慮点
いくつかのアドバンス SQL API を使用してアクセス制御を使用しないようにできます。このような状況が検出されると、AdvancedQueryAccessException が発生します。以下のようにアドバンス照会を使用した場合に、この例外が発生します。
• 副問い合わせ (wt.query.SubSelectExpression)
• MINUS または INTERSECT 複合ステートメント (wt.query.CompoundQuerySpec)
• 外部テーブル (wt.query.ExternalTableExpression)
• 集約関数 (wt.query.SQLFunction)
AVERAGE
MAXIMUM
MINIMUM
SUM
COUNT
• ROWNUM キーワード (wt.query.KeywordExpression)
この例外は、知らないうちにアクセス制御がバイパスされないようにするために発生します。アクセス制御を使用しないこれらのアドバンス SQL 機能を使用することが合理的な場合もあります。このような場合は、アドバンスチェックを実行時に使用不可能にできます。照会仕様クラスは、サーバー側のコードからのみ設定できる advancedQueryEnabled 属性をサポートします。可能な場合は、PersistenceManager の照会および検出 API に渡される照会のインスタンスでこの属性を真に設定し、例外が発生することなくこれらの照会を実行できるようにします。
// Use advanced APIs to build query.
// Disable checking of advance features statement.setAdvancedQueryEnabled(true);
// Execute query with access control
PersistenceHelper.manager.find(statement);
find() メソッドは、アクセス制御が適用されるステートメントを実行します。そのため、アクセス制御に関連するコラムが暗黙的に選択に追加される場合があります。集約関数である INTERSECT および MINUS など一部のアドバンス機能では、これらのコラムの追加により、予測される結果が影響を受ける、または SQL 例外が発生する場合があります。その場合、照会を正常に実行するには、サーバー側でアクセス制御が適用されない query() メソッドを使用します。
PersistenceServerHelper.manager.query(statement);
並べ替え
照会はデータベースレベルで結果データを並べ替えるために使用します。ただし、通常、データベースの並べ替えはページング照会と ColumnExpressions のみを伴う照会に適用されます。その他のタイプの照会では、いくつかの別々の SQL ステートメントとして実装し、並べ替えは照会全体ではなくステートメントごとに行われます。任意の ColumnExpression を並べ替えコラムとして使用できます。OrderBy アイテムを使用して ColumnExpression が StatementSpec に渡されます。また、OrderBy は、並べ替え順 (昇順または降順) およびオプションのロケールを示します。ロケールを指定すると、データベース言語サポートを使用して、任意の文字ベースの属性がそのロケールに関して並べ替えられます。Oracle の場合は、National Language Support (NLS) です (詳細については、Oracle のドキュメンテーションを参照)。Java Locale 値は dbservice.properties エントリを介して Oracle NLS 言語の並べ替え名にマッピングされます。
標準および複合照会では、QuerySpec および CompoundQuerySpec メソッドを介して並べ替えがサポートされています。
QuerySpec.appendOrderBy(OrderBy a_orderBy, int[] a_fromIndicies)
CompoundQuerySpec.appendOrderBy(OrderBy a_orderBy)
QuerySpec メソッドを使用して、QuerySpec の FROM 節に対して OrderBy の ColumnExpression を検証します。CompoundQuerySpec メソッドは検証しません。これらのメソッドは、どちらもステートメントの SELECT 節に ColumnExpression を追加する処理を行いません。この処理は appendSelect() メソッドによって行う必要があります。どちらの場合でも、OrderBy の各 ColumnExpression にコラムエイリアスを設定してください。照会のタイプと関連するサブクラスの番号によって、コラムエイリアスを使用しない場合は実際の SQL ステートメントが無効になる場合があります。コラムエイリアスには、SQL によって使用される単語 (例 : number) を使用しないでください。
以下の例では、並べ替えによる複合照会を構築します。名前によって並べ替えられた部品とドキュメントの名前が返されます。以下に、この照会の SQL を示します。
SELECT A0.bname sortName
FROM WTPart A0
UNION
SELECT A0.bname sortName
FROM WTDocument A0
ORDER BY sortName DESC
以下のコードで、照会の仕様を作成します。最初のコンポーネントの照会は部品です。コラムエイリアスの設定に注意してください。
String sortName = "sortName";
QuerySpec partQuery = new QuerySpec();
int classIndex = partQuery.appendClassList(wt.part.WTPart.class, false);
ClassAttribute partName = new ClassAttribute(wt.part.WTPart.class,
wt.part.WTPart.NAME);
partName.setColumnAlias(sortName);
partQuery.appendSelect(partName, new int[] { classIndex }, false);
以下のセクションでは、照会のドキュメント部分を作成します。同じコラムエイリアスを使用します。
QuerySpec docQuery = new QuerySpec();
classIndex = docQuery.appendClassList(wt.doc.WTDocument.class, false);
ClassAttribute docName =
new ClassAttribute(wt.doc.WTDocument.class, wt.doc.WTDocument.NAME);
docName.setColumnAlias(sortName);
docQuery.appendSelect(docName, new int[] { classIndex }, false);
最後に、これら 2 つのコンポーネント照会を使用して複合照会が作成されます。照会全体に OrderBy が追加されます。デフォルトのロケールを使用して、ユーザーの言語に応じて名前を並べ替えます。
CompoundQuerySpec query = new CompoundQuerySpec();
query.setSetOperator(SetOperator.UNION);
query.addComponent(partQuery);
query.addComponent(docQuery);
query.appendOrderBy(new OrderBy(partName, true
));
アドバンスチェック機能ステートメントを有効にし、サーバー側で照会を正常に実行するには、アクセス制御が適用されていない query() メソッドを使用する必要があります。
query.setAdvancedQueryEnabled(true);
QueryResult queryResult = PersistenceHelper.manager.query (statement);
|
リモートメソッドサーバースタブ内で QuerySpec を実行する必要があります。例の詳細については、「アクセス制御に関する考慮点」を参照してください。
|
結合サポート
照会結合を使用して、別々の表のデータを関連付けます。結合は PersistenceManager のナビゲーションメソッドを使用するか、またはアドホック WhereExpressions を介して実行できます。また、QuerySpec クラスでは、リンククラスおよび Rose モデルで定義された役割を使用した、照会への結合の追加を明示的にサポートします。これにより QuerySpec の柔軟性だけでなく、モデル情報を使用した照会結合の指定が簡単になります。以下の QuerySpec メソッドを使用できます。
appendJoin(int a_linkIndex, String a_role, Persistable a_source)
appendJoin(int a_linkIndex, String a_role, int a_targetIndex)
以下の例では、FolderMembership リンクを介して SubFolder および Part クラスをともに結合する照会を構築します。照会によってすべてのフォルダとフォルダにあるすべての関連部品が返されます。以下のコードで、照会の仕様を作成します。最初のセクションでは、クラスと返される属性を追加します。最後の 2 行のコードでは、FolderMembership リンククラスのモデル化された役割を使用してクラスを結合します。
QuerySpec query = new QuerySpec();
int folderIndex = query.appendClassList(wt.folder.SubFolder.class,
false);
int linkIndex = query.appendClassList(wt.folder.FolderMembership.class,
false);
int partIndex = query.appendClassList(wt.part.WTPart.class, false);
query.appendSelect(new ClassAttribute(wt.folder.SubFolder.class,
wt.folder.SubF
older.NAME),
new int[] { folderIndex } , false);
query.appendSelect(new ClassAttribute(wt.part.WTPart.class,
wt.part.WTPart.NAME),
new int[] { partIndex }, false);
query.appendJoin(linkIndex, wt.folder.FolderMembership.FOLDER_ROLE,
folderIndex);
query.appendJoin(linkIndex, wt.folder.FolderMembership.MEMBER_ROLE,
partIndex);