TopLinkの式フレームワークを使用すると、ドメイン・オブジェクト・モデルに基づいて問合せの検索基準を指定できます。
この章の内容は次のとおりです。
TopLinkの式フレームワークは、次のクラスを通じてメソッドを提供します。
例110-1は、Expression
クラスの使用方法を示します。
例110-2は、ExpressionMath
クラスの使用方法を示します。
例110-2 ExpressionMathクラスの使用
ExpressionMath.abs(ExpressionMath.subtract(emp.get("salary"), emp.get("spouse").get("salary")).greaterThan(10000)
このように機能を分けることで、TopLinkの式は、java.lang.Math
クラスに似た数値演算機能を提供しながらも、Expression
およびExpressionMath
クラスが必要以上に複雑になることを防ぐことができます。
データベースにアクセスする場合、式は次の点でSQLよりも優れています。
データベースが抽象化されるため、式の方が管理が容易です。
ディスクリプタまたはデータベース表に変更を加えても、アプリケーションの問合せ構造に影響を与えません。
式では、Javaの通常のコール方法に似せてQuery
インタフェースを標準化するため、読みやすさが向上します。たとえば、Employee
クラスのAddress
オブジェクトから通りの名前を取得するのに必要なJavaコードは次のとおりです。
emp.getAddress().getStreet().equals("Meadowlands");
同じ情報を取得するための式はこれに似ています。
emp.get("address").get("street").equal("Meadowlands");
式を使用すると、読取り問合せによって、同じリレーションシップを共有する2つのクラスの間で問合せを透過的に行うことができます。これらのクラスがデータベース内の複数の表に格納されている場合、適切な結合文が自動的に生成され、両方の表から情報が返されます。
式は複雑な操作を単純化します。たとえば、次のJavaコードは、Meadowlandsに住み、給与が10,000を超える従業員をすべて取得します。
ExpressionBuilder emp = new ExpressionBuilder(); Expression exp = emp.get("address").get("street").equal("Meadowlands"); Vector employees = session.readAllObjects(Employee.class, exp.and(emp.get("salary").greaterThan(10000)));
このコードから適切なSQLが自動的に生成されます。
SELECT t0.VERSION, t0.ADDR_ID, t0.F_NAME, t0.EMP_ID, t0.L_NAME, t0.MANAGER_ID, t0.END_DATE, t0.START_DATE, t0.GENDER, t0.START_TIME, t0.END_TIME,t0.SALARY FROM EMPLOYEE t0, ADDRESS t1 WHERE (((t1.STREET = 'Meadowlands')AND (t0.SALARY > 10000)) AND (t1.ADDRESS_ID = t0.ADDR_ID))
属性: 永続クラスのマップ済属性または問合せキーを表します。
演算子: GreaterThan
、Equal
、Like
などのブール・ロジックを実現する表現方法です。
定数または比較: オブジェクトの選択に使用される値を参照します。
次のコードを見てみましょう。
expressionBuilder.get("lastName").equal("Smith");
属性はlastName
です。
演算子はequal
です。
定数は文字列"Smith
"です。
expressionBuilder
には、データベースから読み取られる1つ以上のオブジェクトに置き換わります。この例では、expressionBuilder
は従業員を表しています。
式を構成する際には、次の構成要素を使用できます。
式では、AND
、OR
、NOT
などの標準的なブール演算子が使用されます。複数の式を組み合せて、さらに複雑な式を構成することができます。例110-3は、選択された人によって管理され、予算が1,000,000以上のプロジェクトを問い合せるコードの一部分を示します。
例110-3 式でのブール・ロジックの使用
ExpressionBuilder project = new ExpressionBuilder(); Expression hasRightLeader, bigBudget, complex; Employee selectedEmp = someWindow.getSelectedEmployee(); hasRightLeader = project.get("teamLeader").equal(selectedEmp); bigBudget = project.get("budget").greaterThanEqual(1000000); complex = hasRightLeader.and(bigBudget); Vector projects = session.readAllObjects(Project.class, complex);
関数
TopLinkの式では、様々なデータベース関数がサポートされます。次にその一部を示します。
toUpperCase
toLowerCase
toDate
decode
locate
monthsBetween
nextDay
replace
reverse
substring
translate
注意: 一部の関数はデータベース・プラットフォームに固有です。 |
データベース関数を使用すると、より柔軟な問合せを定義できます。これらの関数は、SELECT
句を使用したレポート問合せの項目で、またはWHERE
句を使用した問合せの選択基準の比較で使用できます。例110-4は、SMART、Smith、Smothersなどの複数の姓に一致するコードの一部分を示します。
ほとんどの関数は、式のtoUpperCase
などのメソッドを使用してアクセスできます。
用途の限定されている関数もあります。例110-5に示すように、ascending
関数やdescending
関数は、結果を昇順または降順に配置するために順序付けの式内でのみ使用します。
ReportQuery
(108.7.5項「レポート問合せ」を参照)では、average
、minimum
、maximum
、sum
などの集計関数を使用できます。
演算子
演算子は、2つの値を比較する関係演算子です。TopLinkの式では、次の演算子がサポートされています。
like
notLike
equal
notEqual
lessThan
lessThanEqual
equalsIgnoreCase
greaterThan
greaterThanEqual
in
notIn
between
notBetween
例110-4は、like演算子の使用方法を示します。
数値演算関数は、ExpressionMath
クラスを通じて使用できます。式における数値演算関数のサポートは、Javaクラスjava.lang.Math
によるサポートに似ています。例110-6は、abs
およびsubtract
メソッドの使用例を示します。
OracleデータベースXMLType
列にマップされたデータに対する問合せを構成する場合は、次の演算子を使用できます。
extract
: XPath文字列をとり、元のドキュメントのうち、XPathに一致する部分のXMLTypeを返します。
extractValue
: XPath文字列をとり、XPathが指すノードの内容に基づいて、数値または文字列の値を返します。
existsNode
: Xpath式をとり、XPathに一致するノードの数を返します。
getStringVal
: XMLType
オブジェクトの文字列表現を取得します。
getNumberVal
: XMLType
オブジェクトの数値表現を取得します。
isFragment
: XMLが整形式文書である場合、0に評価します。文書がフラグメントである場合、1に評価します。
例110-7は、問合せにおける抽出演算子の使用方法を示します。
Expression
のメソッドgetFunction
を使用すると、TopLinkで直接サポートされていないデータベース関数にアクセスできます。例110-8は、Expression
APIの関数などがサポートされていない場合でも、式内からVacationCredit
という名前のデータベース関数にアクセスする方法を示します。
例110-8 Expression APIによってサポートされていないデータベース関数の使用
emp.get("lastName").getFunction("VacationCredit").greaterThan(42)
この式では、次のSQLが生成されます。
SELECT . . . WHERE VacationCredit(EMP.LASTNAME) > 42
Expression
APIには、引数を指定できる、他の形式のgetFunction
メソッドもあります。詳細は、『Oracle Fusion Middleware Java API Reference for Oracle TopLink』を参照してください。
ユーザー作成のカスタム関数にアクセスすることもできます。TopLinkのカスタム関数の作成方法の詳細は、110.8項「ユーザー定義関数の作成と使用」を参照してください。
式には、別の永続クラスとの1対1リレーションシップを持つ属性を含めることができます。当然、1対1リレーションシップは単一行を返すSQL結合に変換されます。
例110-9は、従業員の住所のフィールドにアクセスする、コードの一部分を示します。
例110-9は、address
外部キーに基づいてEMPLOYEE表をADDRESS表に結合し、国名をチェックするという操作に相当します。
これらのリレーションシップは無限にネストさせることができるため、次のような複雑な情報を問い合せることも可能です。
project.get("teamLeader").get("manager").get("manager").get("address").get("street")
1対多、多対多、ダイレクト・コレクション、集約コレクションなどの複雑なリレーションシップに対して問合せを行うことができます。このようなタイプのリレーションシップはオブジェクトごとに単一行を返す結合に直接マップされないため、これらのリレーションシップを表す式は作成方法が複雑です。
この項の内容は次のとおりです。
結合は、2つ以上の表からの行を組み合せるリレーショナル・データベース問合せです。問合せのFROM
句に複数の表を記述すると、必ずリレーショナル・データベースでは結合が実行されます。問合せの選択リストでは、これらの表のうちの任意の表から任意の列を選択できます。
内部結合(単純結合とも呼ばれる)は、2つ以上の表の結合で、結合条件を満たす行のみを返します。
外部結合は、内部結合の結果を拡張したものです。外部結合では、結合条件を満たすすべての行を返します。また、1つの表の結合条件がその他の表では満たされない場合には、その表の行の一部またはすべてを返します。外部結合は、左外部結合と右外部結合に分類できます。
表AおよびBの左外部結合を実行する問合せでは、A内の行をすべて返します。B内に一致する行を持たないA内の行すべてに対しては、Bの列を含む選択リストの式に対してnullが返されます。
表AおよびBの左外部結合を実行する問合せでは、B内の行をすべて返します。A内に一致する行を持たないB内の行すべてに対しては、Aの列を含む選択リストの式に対してnullが返されます。
結合式を使用して問合せを行うと、結合が使用され、他のオブジェクトの値、または同じオブジェクトの一部を表す他の表の値をチェックすることができます。これはほとんどの状況でうまくいきますが、リレーションシップの一方が存在しない1対1リレーションシップに対して問合せを行った場合に問題が発生することがあります。
たとえば、Employee
オブジェクトがAddress
オブジェクトを所有しているとします。しかし、Address
が不明な場合、これはオブジェクト・レベルではnull
であり、データベース・レベルではnullの外部キーを持つことになります。このリレーションシップを走査する問合せを試行すると、オブジェクトが欠落しているために、予期しない結果が返されます。次の式について考えてみます。
(emp.get("firstName").equal("Steve")).or(emp.get("address"). get("city").equal("Ottawa"))
この場合、住所を持たない従業員は、名前に関係なく結果セットには含まれません。オブジェクト・レベルでは明白ではありませんが、この動作はリレーショナル・データベースの特性の基本となります。
外部結合をサポートしているデータベースでは、外部結合によってこの問題が解決します。この例では、外部結合を使用することで、住所が不明であってもSteveという名前のすべての従業員が結果セットに含まれるという、予期した結果が得られます。
外部結合を実装するには、Expression
のメソッドget
のかわりにgetAllowingNull
を使用します。同様に、Expression
のメソッドであるanyOf
のかわりにanyOfAllowingNone
を使用します。
次に例を示します。
(emp.get("firstName").equal("Steve")).or( emp.getAllowingNull("address").get("city").equal("Ottawa"))
外部結合のサポートと構文は、データベースとデータベース・ドライバによって大きく異なります。TopLinkでは、ほとんどのデータベースの外部結合がサポートされています。
選択基準、順序付け(109.2.1.5項「読取り順序の指定」を参照)、レポート問合せ(108.7.5項「レポート問合せ」を参照)、部分オブジェクト(108.7.1.3項「部分オブジェクト問合せ」を参照)、1対1リレーションシップ・マッピング(28.8項「マッピング・レベルでの結合の構成」を参照)および結合読取り(108.7.1.5項「結合読取りとオブジェクト・レベルの読取り問合せ」を参照)など、式を使用する場所ではどこでも結合を使用できます。
表110-1に示すExpression APIを使用して、内部および外部結合式を構成します。
表110-1 結合用のExpression API
Expression API | 結合のタイプ | マッピングのタイプ |
---|---|---|
|
inner |
1対1 |
|
外部 |
1対1 |
|
inner |
1対多、多対多 |
|
外部 |
1対多、多対多 |
1対多または多対多のリレーションシップに対して問合せを行うには、anyOf
操作を使用します。その名前が示すように、この操作では問合せ基準を満たすリレーションシップの多くの側面ですべての項目を返す問合せがサポートされます。
例110-10は、給与が10,000ドル未満の従業員を1人以上(1対多リレーションシップを通じて)管理する従業員を返す式を示します。
例110-11は、同様の方法で多対多リレーションシップ全体に対して問い合せる方法を示します。
これらの問合せはSQLに変換されます。SQLでは、DISTINCT
句を使用して関連のある表を結合し、重複を排除します。TopLinkでは、例110-10を次のSQLに変換します。
SELECT DISTINCT . . . FROM EMP t1, EMP t2 WHERE t2.MANAGER_ID = t1.EMP_ID AND t2.SALARY < 10000
ObjectLevelReadyQuery
内で1対1および1対多の結合式を使用して、問合せごとに結合を構成できます(108.7.1.5項「結合読取りとオブジェクト・レベルの読取り問合せ」を参照)。
また、マッピング・レベルで結合を構成することもできます(28.8項「マッピング・レベルでの結合の構成」を参照)。
注意: anyOf を1回コールした場合の結果は、2回コールした場合の結果と異なります。たとえば、市外局番が613で、かつ電話番号が123-4599の従業員を問い合せる場合は、anyOf を1回と一時変数を使用します。市外局番が613の従業員と、電話番号が123-4599の従業員を問い合せる場合は、anyOf を2回コールします。 |
リレーションシップ・マッピングは、数多くの様々なオブジェクトのデータを取得するという点で、通常の問合せとは異なります。このような問合せを指定できるようにするには、問合せの実行時に引数を指定します。getParameter
およびgetField
メソッドを使用して、引数の値を取得します。
パラメータ化された式では、定数ではなく変数に基づいて検索と比較が実行されます。そのため、状況依存の情報を取得する式を作成できます。この手法は、EJBファインダ(108.15項「EJB 2.n CMPファインダ」を参照)を定義する場合に便利です。
パラメータ化された式の場合、リレーションシップ・マッピングが現在のコンテキストに基づいて1つのオブジェクトまたはオブジェクトのコレクションを取得する方法を認識している必要があります。たとえば、Employee
からAddress
への1対1マッピングでは、Employee
表の外部キー情報に基づき、データベースに対して住所を問い合せる必要があります。各マッピングは、マッピングに指定した情報に基づいて自動的に構成される問合せを含んでいます。式を手動で指定するには、マッピング・カスタマイズ・メカニズムを使用します。
パラメータ化された式は、再利用可能な問合せ(108.8項「名前付き問合せ」を参照)の作成に使用できます。
Expression
のメソッドgetParameter
は、問合せのパラメータとなる式を返します。これにより、ユーザー入力を検索基準に含めた問合せを作成できます。パラメータは、ディスクリプタの行から取得されたフィールドの完全修飾名、または引数の一般名であることが必要です。
この方法で構成したパラメータは現在の問合せ全体に対して有効であるため、このメッセージをすべての式オブジェクトに送信することができます。
例110-12は、カスタム問合せを使用して、名前で従業員を検索する方法を示します。
例110-12 カスタム問合せにおけるパラメータ化された式の使用
Expression firstNameExpression; ReadObjectQuery query = new ReadObjectQuery(Employee.class); ExpressionBuilder emp = query.getExpressionBuilder(); firstNameExpression = emp.get("firstName").equal(emp.getParameter("firstName")); query.setSelectionCriteria(firstNameExpression); query.addArgument("firstName"); Vector v = new Vector(); v.addElement("Sarah"); Employee e = (Employee) session.executeQuery(query, v);
例110-13は、カスタム問合せを使用して特定の従業員と同じ都市に住む従業員をすべて検索する方法を示します。
例110-13 ネストされ、パラメータ化された式の使用
Expression addressExpression; ReadObjectQuery query = new ReadObjectQuery(Employee.class); ExpressionBuilder emp = query.getExpressionBuilder(); addressExpression = emp.get("address").get("city").equal( emp.getParameter("employee").get("address").get("city")); query.setName("findByCity"); query.setSelectionCriteria(addressExpression); query.addArgument("employee"); Vector v = new Vector(); v.addElement(employee); Employee e = (Employee) session.executeQuery(query, v);
例110-14は、デフォルトではない選択基準を使用して、クラスPolicyHolder
からPolicy
への単純な1対多マッピングを取得する方法を示します。POLICY
表のSSN
フィールドは、HOLDER
表のSSN
フィールドの外部キーです。
例110-14 マッピングにおけるパラメータ化された式の使用
OneToManyMapping mapping = new OneToManyMapping();
mapping.setAttributeName("policies");
mapping.setGetMethodName("getPolicies");
mapping.setSetMethodName("setPolicies");
mapping.setReferenceClass(Policy.class);
// Build a custom expression here rather than using the defaults
ExpressionBuilder policy = new ExpressionBuilder();
mapping.setSelectionCriteria(policy.getField("POLICY.SSN")).equal(policy.
getParameter("HOLDER.SSN")));
Expression
のメソッドgetField
は、特定の名前のデータベース・フィールドを表す式を返します。このメソッドを使用すると、マッピングの選択基準を構成できます。引数は、必要なフィールドの完全修飾名です。フィールドは現在の問合せ全体に対して有効ではないため、このフィールドの取得元の表を表す式に、このメソッドを送信する必要があります。110.6項「データ問合せとデータ式」も参照してください。
例110-15は、Expression
のメソッドgetField
の使用方法を示します。
問合せキーとは、データベース・フィールド名の、スキーマ非依存の別名です。
問合せキーは、リレーショナル・データベース・プロジェクトでのみサポートされています。
問合せキーは、すべてのダイレクト・マッピングおよびリレーションシップ・マッピングで使用するために自動的に生成されます。問合せキーの名前は、クラス属性名です。
問合せキーの作成および変更方法の詳細は、119.10項「問合せキーの構成」を参照してください。
例110-16は、問合せキーfirstName
を、それに対応する直接にマップ済のEmployee
属性に対して使用する方法を示します。
例110-16 自動生成された問合せキーの式での使用
Vector employees = session.readAllObjects(Employee.class, new ExpressionBuilder().get("firstName").equal("Bob"));
例110-17は、TopLinkの式フレームワーク内で1対1問合せキーを使用する方法を示します。
例110-17 式での1対1問合せキーの使用
ExpressionBuilder employee = new ExpressionBuilder(); Vector employees = session.readAllObjects(Employee.class, employee.get("address").get("city").equal("Ottawa"));
コレクション・リレーションシップでの個別の結合を定義する1対多問合せキーおよび多対多問合せキーにアクセスするには、Expression
のメソッドanyOf
を使用します。
式では、副問合せ(SQLの副選択)とパラレル選択がサポートされます。副問合せを作成するには、式ビルダーを1つ使用します。パラレル選択の場合、単一の問合せを定義するときに式ビルダーを複数使用します。そうすることで、関連のないオブジェクトの結合をオブジェクト・レベルで指定できます。
一部の問合せでは、その中に含まれる他の問合せ(副問合せ)の結果が比較されます。SQLは、副選択によってこの比較をサポートします。TopLinkの式は、副選択をサポートする副問合せを提供します。
副問合せを使用すると、集計値(counts
、min
、max
)や関連のないオブジェクト(exists
、in
、comparisons
)に対して問合せを行う複雑な式を定義できます。副問合せを取得するには、レポート問合せのインスタンスを任意の式比較操作に渡すか、式ビルダーでsubQuery
操作を使用します。副問合せに親問合せと同じ参照クラスが指定されている必要はありません。副問合せ専用の式ビルダーを使用する必要があります。
副問合せはネストさせることも、並列に使用することもできます。副問合せでカスタムSQLを使用することも可能です。
単一の値を受け入れる式比較操作(equal
、greaterThan
、lessThan
)の場合は、副問合せの結果として単一の値が返される必要があります。値セットを受け入れる式比較操作(in
、exists
)の場合は、副問合せの結果として値セットが返される必要があります。
例110-18は、部下が6人以上いるすべての従業員に一致する式を作成する方法を示します。
例110-18 比較およびカウント操作を使用した副問合せの式
ExpressionBuilder emp = new ExpressionBuilder(); ExpressionBuilder managedEmp = new ExpressionBuilder(); ReportQuery subQuery = new ReportQuery(Employee.class, managedEmp); subQuery.addCount(); subQuery.setSelectionCriteria(managedEmp.get("manager") .equal(emp)); Expression exp = emp.subQuery(subQuery).greaterThan(5);
例110-19は、オタワ市で給与が最も高い従業員に一致する式を作成する方法を示します。
例110-19 比較および最大操作を使用した副問合せの式
ExpressionBuilder emp = new ExpressionBuilder(); ExpressionBuilder ottawaEmp = new ExpressionBuilder(); ReportQuery subQuery = new ReportQuery(Employee.class, ottawaEmp); subQuery.addMax("salary"); subQuery.setSelectionCriteria(ottawaEmp.get("address").get("city").equal("Ottawa")); Expression exp = emp.get("salary").equal(subQuery).and(emp.get("address").get("city").equal("Ottawa"));
例110-20は、プロジェクトを持たないすべての従業員に一致する式を作成する方法を示します。
例110-20 notExists操作を使用した副問合せの式
ExpressionBuilder emp = new ExpressionBuilder(); ExpressionBuilder proj = new ExpressionBuilder(); ReportQuery subQuery = new ReportQuery(Project.class, proj); subQuery.addAttribute("id"); subQuery.setSelectionCriteria(proj.equal(emp.anyOf("projects")); Expression exp = emp.notExists(subQuery);
パラレル式を使用すると、関連のないオブジェクトを比較できます。パラレル式には複数の式ビルダーが必要ですが、レポート問合せを使用する必要はありません。それぞれの式に専用の式ビルダーが必要です。さらに、class
を引数としてとるコンストラクタを使用する必要があります。パラレル式のクラスは同一である必要はありません。また、1つの問合せの中に複数のパラレル式を作成できます。
複数の式ビルダーのうち1つのみが、その問合せのプライマリ式ビルダーとみなされます。このプライマリ・ビルダーは、ゼロ引数の式コンストラクタを使用します。このコンストラクタのクラスは問合せから取得されます。
例110-21は、性別の異なる他の従業員と同じ姓を持つすべての従業員と一致する式を作成する方法と、返される結果が配偶者である可能性を示します。
式を使用して、オブジェクトではなくデータを取得できます。これは、外部キーやバージョン・フィールドなど、データベース内のマップされていない情報を扱う際の一般的な方法です。
通常、オブジェクトを問い合せる式ではオブジェクトの属性が参照されます。その結果、他のオブジェクトが参照される場合もあります。データ式では表とそのフィールドが参照されます。1つの問合せの中でデータ式とオブジェクト式を組み合せることができます。TopLinkは、データを問い合せる式で使用する主なメソッドとして、getField
とgetTable
の2つを提供します。
getField
メソッドを使用すると、オブジェクトのマップされていない表、またはマップされていないフィールドからデータを取得できます。どちらの場合も、フィールドはそのオブジェクトのクラスで表される表の一部である必要があります。表の一部でない場合は、問合せを実行したときに例外が発生します。
getField
メソッドを使用して、オブジェクトの外部キー情報を取得することもできます。
例110-22は、オブジェクトに対してデータ式のメソッド(演算子)getField
を使用する方法を示します。
getTable
メソッドは、データベース内のマップされていない表を表す式を返します。この式は、getField
メソッドを使用したときに、マップされていないフィールドを取得するためのコンテキストを提供します。
例110-23は、getField
およびgetTable
を同一の式内で併用する方法を示します。
例110-23 getTableとgetFieldの併用
builder.getTable("[TABLE_NAME]").getField("[FIELD_NAME]").equal("[ARGUMENT]");
一般的に、getTable
およびgetField
メソッドを使用するのは、多対多リレーションシップをサポートするリンク表(参照表)から情報を取得する場合です。
例110-24では、リンク表を使用する多対多リレーションシップを読み取り、リンク表の追加フィールドのチェックも行っています。このコードは、従業員のマネージャをデータ問合せの基礎として使用し、オブジェクト問合せとデータ問合せを組み合せたものです。プロジェクトIDのパラメータ化も使用しています。
ExpressionBuilder emp = new ExpressionBuilder(); Expression manager = emp.get("manager"); Expression linkTable = manager.getTable("PROJ_EMP"); Expression empToLink = emp.getField("EMPLOYEE .EMP_ID").equal(linkTable.getField("PROJ_EMP.EMP_ID"); Expression projToLink = linkTable.getField("PROJ_EMP .PROJ_ID").equal(emp.getParameter("PROJECT.PROJ_ID")); Expression extra = linkTable.getField("PROJ_EMP.TYPE").equal("W"); query.setSelectionCriteria((empToLink.and(projToLink)).and(extra));
式は、Oracle JDeveloper、TopLink WorkbenchまたはJavaを使用して作成できます。
Oracle JDeveloperまたはTopLink Workbenchを使用すると、名前付き問合せで使用する基本的な式を作成できます(110.7.1項「TopLink Workbenchを使用した式の作成方法」を参照)。
Javaコードを使用すると、より複雑な式を作成し、Expression APIの機能を完全活用できます(110.7.2項「Javaを使用した式の作成方法」を参照)。
名前付き問合せ用にTopLinkの式を作成するには、次の手順を実行します。
名前付き問合せの形式タブの「編集」をクリックするか、問合せ文字列をダブルクリックします。「式ビルダー」ダイアログ・ボックスが表示されます。
詳細は、108.8項「名前付き問合せ」を参照してください。
図110-1の数字の付いたコールアウトは、次のユーザー・インタフェース・コンポーネントを示します。
式ツリー
引数
「追加」または「ネストの追加」をクリックして、新規の式を作成します。TopLinkでは、各ノードとネストされたノードに順序番号を割り当てます。
既存の式を削除する場合は、「削除」をクリックします。
ノードを選択し、「論理演算子」リストを使用して、ノードの演算子(AND、OR、Not ANDまたはNot OR)を指定します。
次の表を使用して、各式の引数フィールドを指定します。
フィールド | 説明 |
---|---|
第1引数 | 「編集」をクリックし、第1引数の問合せキーを選択します。「問合せキーの選択」ダイアログ・ボックスが表示されます。
110.7.1.1項「引数の追加」に進みます。 |
演算子 | TopLinkでの式の評価方法を指定します。有効な演算子には、Equal、Not Equal、Equal Ignore Case、Greater Than、Greater Than Equal、Less Than、Less Than Equal、Like、Not Like、Like Ignore Case、Is NullおよびNot Nullがあります。 |
第2引数 | 第2引数を指定します。
110.7.1.1項「引数の追加」に進みます。 |
「OK」をクリックします。TopLink Workbenchで、式が「名前付き問合せ」タブに追加されます。
各式には、評価する要素(引数)があります。Is NullまたはNot Null演算子を使用する式で必要な引数は、1つのみです。
新しい引数を追加するには、次の手順を実行します。
既存の式を選択するか、あるいは「追加」または「ネストの追加」をクリックして新規の式を名前付き問合せに追加します。
属性を選択し、問合せでnull値を受け入れるかどうかを指定し、「OK」をクリックします。
「NULLを許容」および「Noneを許容」オプションを使用すると、外部結合で使用する式を定義できます。
「NULLを許容」オプションを選択すると、ExpressionBuilder
のメソッドgetAllowingNull
が使用されます。
「Noneを許容」オプションを選択すると、ExpressionBuilder
のメソッドanyOfAllowingNone
が使用されます。
詳細は、110.2.7.2項「結合でのTopLink Expression APIの使用」を参照してください。
「演算子」リストを使用して、TopLinkでの式の評価方法を指定します。
「第2引数」の場合は、「リテラル」、「問合せキー」または「パラメータ」を選択します。
この手順を、各式またはネストした式について繰り返します。
例110-25 式のサンプル
後述の式では、次の条件に当てはまる従業員を検索します。
Jonesという姓のマネージャがいるか、マネージャがいません。
Betaという名前が付くプロジェクトかプロジェクトID 4に従事しています。
カナダ在住で給与が25,000を超えています。
アメリカ在住で給与が37,500を超えています。
AND 1.manager(Allows Null).lastName EQUAL "Jones" 2.OR 2.1.projects.name LIKE "BETA" 2.2.projects.id EQUAL "4" 3.OR 3.1.AND 3.1.1.address.country EQUAL "Canada" 3.1.2.salary GREATER THAN "25000" 3.2.AND 3.1.1.address.country EQUAL "United States" 3.1.2.salary GREATER THAN "37500"
Javaコードで式を作成するには、Expression
クラスまたはExpressionBuilder
のメソッドget
を使用します。
ExpressionBuilder
は、問合せ対象のオブジェクトのかわりとなります。問合せを構成するには、オブジェクトの属性に対応するメソッドをExpressionBuilder
に対してコールします。ExpressionBuilder
オブジェクトには、問合せ対象のオブジェクトのタイプに応じた名前を付けることをお薦めします。
注意: ExpressionBuilder のインスタンスは特定の問合せ専用です。既存のビルダーを使用して別の問合せを作成しようとしないでください。既存のビルダーには最初の問合せに関連した情報が残っているためです。 |
例110-26は、問合せキーlastName
を使用して、フィールド名L_NAME
を参照する方法を示します。
例110-26 ExpressionBuilderを使用した単純な式の作成
Expression expression = new ExpressionBuilder().get("lastName").equal("Young");
例110-27は、and
論理演算子を使用して、小さな2つの式を組み合せることによって、複雑な式を作成する方法を示します。
例110-27 AND論理演算子を使用した2つの式の組合せ
ExpressionBuilder emp = new ExpressionBuilder(); Expression exp1, exp2; exp1 = emp.get("firstName").equal("Ken"); exp2 = emp.get("lastName").equal("Young"); return exp1.and(exp2);
例110-28は、notLike
演算子を使用して式を作成する方法を示します。
同じ関数の実装方法がデータベースによって異なることがあります。たとえば、データが昇順で返されることを指定する引数は、ASC
またはASCENDING
です。このような相違に対処するために、TopLinkではリレーショナル・データベースによって異なる関数やその他の演算子を認識できます。
TopLinkにはプラットフォーム固有の演算子のほとんどが用意されていますが、必要に応じて、独自の演算子を作成できます。
ユーザー定義関数を作成するには、ExpressionOperator
クラスを使用します。
ExpressionOperator
には、セレクタと文字列のVector
を指定します。
セレクタは、ユーザーが関数の参照に使用する識別子(id)です。
文字列は、関数の出力に使用される定数文字列です。出力時には、文字列は関数の引数に置き換わります。
演算子が前置演算子と後置演算子のどちらであるかも指定できます。前置演算子の場合、最初の定数文字列が最初の引数の前に出力されます。後置演算子の場合は、最初の引数の後に出力されます。
ユーザー定義関数を作成する場所と、それをTopLinkの式フレームワークに追加する方法は、その新しい関数をすべてのデータベース・プラットフォームで利用するのか、特定のデータベース・プラットフォームでのみ利用するのかによって異なります。
この項の内容は次のとおりです。
独自プラットフォームの特定の操作をオーバーライドする関数を作成するには、次の手順を実行します。
希望のDatabasePlatform
(oracle.toplink.platform.database
またはoracle.toplink.platform.database.oracle
パッケージに含まれるもの)のサブクラスを作成します。DatabasePlatform
には、protectedスーパークラス・メソッドaddOperator
をコールするpublicメソッドが用意されています。
... public class MyDatabasePlatform extends DatabasePlatform { protected void initializePlatformOperators() { super.initializePlatformOperators(); // Create user-defined function ExpressionOperator toUpper = new ExpressionOperator(); toUpper.setSelector(ExpressionOperator.ToUpperCase); Vector v = new Vector(); v.addElement("UPPERCASE("); v.addElement(")"); toUpper.printAs(v); toUpper.bePrefix(); toUpper.setNodeClass(FunctionExpression.class); // Make it available to this platform only addOperator(toUpper); } }
このプラットフォーム・サブクラスを使用するようにセッションを構成します(20.2項「プロジェクト・レベルでのリレーショナル・データベース・プラットフォームの構成」または98.2項「セッション・レベルでのリレーショナル・データベース・プラットフォームの構成」を参照)。
すべてのプラットフォームで利用可能な関数を作成するには、例110-29に示すように、ExpressionOperator
のメソッドaddOperator
を使用します。
例110-29 すべてのプラットフォームに対するtoUpper関数の追加
ExpressionOperator toUpper = new ExpressionOperator(); toUpper.setSelector(600); Vector v = new Vector(); v.addElement("NUPPER("); v.addElement(")"); toUpper.printAs(v); toUpper.bePrefix(); toUpper.setNodeClass(FunctionExpression.class); ExpressionOperator.addOperator(toUpper);
注意: setSelector メソッドの番号は、定数値で表します。この番号が500を超えていることを確認してください(500以下の番号はTopLinkで予約されています)。 |
例110-30は、すべてか特定のいずれのプラットフォーム用に関数を追加するのかに関係なく、Expression
のメソッドgetFunction
を使用して、定数値600で示されたユーザー定義式演算子にアクセスする方法を示します。
例110-30 ユーザー定義関数へのアクセス
ReadObjectQuery query = new ReadObjectQuery(Employee.class); ExpressionBuilder builder = query.getExpressionBuilder(); Expression functionExpression = builder.get("firstName"). getFunction(600).equal("BOB"); query.setSelectionCriteria(functionExpression); session.executeQuery(query);