この章では、EclipseLinkの式フレームワークを使用して、ドメイン・オブジェクト・モデルに基づいて問合せの検索基準を指定する方法について説明します。
この章の内容は次のとおりです。
EclipseLinkの式フレームワークは、次のクラスを通じてメソッドを提供します。
Expression
クラスは、toUpperCase
など、最も一般的な関数を提供します。
ExpressionMath
クラスは、数値演算メソッドを提供します。
このように機能を分けることで、EclipseLinkの式は、java.lang.Math
クラスに類似した数値演算機能を提供しながらも、Expression
およびExpressionMath
クラスが必要以上に複雑になることを防ぐことができます。
データベースにアクセスする場合、式は次の点でSQLよりも優れています。
データベースが抽象化されるため、式の方が管理が容易です。
ディスクリプタまたはデータベース表に変更を加えても、アプリケーションの問合せ構造に影響を与えません。
式では、Javaの通常のコール方法に似せてQuery
インタフェースを標準化するため、読みやすさが向上します。
式を使用すると、読取り問合せによって、同じリレーションシップを共有する2つのクラスの間で問合せを透過的に行うことができます。これらのクラスがデータベース内の複数の表に格納されている場合、EclipseLinkは適切な結合文を自動的に生成し、両方の表から情報を返します。
式は複雑な操作を単純化します。
通常、単純な式は次の3つの部分で構成されています。
属性: 永続クラスの問合せキーまたはマップされた属性を表します。
演算子: GreaterThan
、Equal
またはLike
などのブール・ロジックを実装する式メソッドです。
定数または比較: オブジェクトの選択に使用される値を参照します。
次のコード・フラグメントでは、属性はlastName
、演算子はequal
、定数は文字列"Smith
"です。expressionBuilder
には、データベースから読み取られる1つ以上のオブジェクトに置き換わります。この例では、expressionBuilder
は従業員を表しています。
expressionBuilder.get("lastName").equal("Smith");
Expression
を作成する場合、次の構成要素を使用できます。
式では、標準のブール演算子(AND
、OR
、NOT
など)を使用し、複数の式を結合してより複雑な式を作成できます。
EclipseLinkでは、様々なデータベースに変換される標準の演算子名を使用して、多くのデータベース関数がサポートされます。EclipseLinkの演算子は、同等の関数(関数のセット)を持つ任意のデータベースでサポートされます。サポートされるすべての関数と演算子の詳細およびリストは、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の「OPERATOR」および「FUNCTION」を参照してください。
EclipseLinkの式は、Expression
クラスに記載された、様々なデータベース関数をサポートしています。データベース関数を使用すると、より柔軟な問合せを定義できます。これらの関数は、SELECT
句を使用したレポート問合せで、またはWHERE
句を使用した問合せの選択基準の比較で使用できます。
注意: 一部の関数はデータベース・プラットフォームに固有です。 |
演算子は、2つの値を比較する関係演算子です。EclipseLinkの式演算子は、ExpressionOperator
クラスに記載されています。
数値演算関数は、ExpressionMath
クラスを通じて使用できます。式における数値演算関数のサポートは、Javaクラスjava.lang.Math
によるサポートに似ています。
OracleデータベースXMLType
列にマップされたデータに対する問合せを構成する場合は、次の演算子を使用できます。
extract
: XPath文字列をとり、元のドキュメントのうち、XPathに一致する部分のXMLTypeを返します。
extractValue
: XPath文字列をとり、XPathが指すノードの内容に基づいて、数値または文字列の値を返します。
existsNode
: XPath式をとり、XPathに一致するノードの数を返します。
getStringVal
: XMLType
オブジェクトの文字列表現を取得します。
getNumberVal
: XMLType
オブジェクトの数値表現を取得します。
isFragment
: XMLが整形式文書である場合、0に評価します。文書がフラグメントである場合、1に評価します。
Expression
のメソッドgetFunction
を使用すると、EclipseLinkで直接サポートされていないデータベース関数にアクセスできます。Expression
APIには、引数を指定できる、他の形式のgetFunction
メソッドもあります。独自のカスタム関数も作成できます。詳細は、Oracle TopLink Java APIリファレンスを参照してください。
式には、別の永続クラスとの1対1リレーションシップを持つ属性を含めることができます。当然、1対1リレーションシップは単一行を返すSQL結合に変換されます。
1対多、多対多、ダイレクト・コレクション、集約コレクションなどの複雑なリレーションシップに対して問合せを行うことができます。このようなタイプのリレーションシップはオブジェクトごとに単一行を返す結合に直接マップされないため、これらのリレーションシップを表す式は作成方法が複雑です。
この項の内容は次のとおりです。
結合は、2つ以上の表からの行を組み合せるリレーショナル・データベース問合せです。問合せのFROM
句に複数の表を記述すると、必ずリレーショナル・データベースでは結合が実行されます。問合せの選択リストでは、これらの表のうちの任意の表から任意の列を選択できます。
内部結合(単純結合とも呼ばれる)は、2つ以上の表の結合で、結合条件を満たす行のみを返します。
外部結合は、内部結合の結果を拡張します。外部結合は、結合条件を満たすすべての行と、結合条件を満たす行を除いた、一方の表のすべての行を戻します。外部結合は、右または左に分類できます。
表AおよびBの左外部結合を実行する問合せでは、A内の行をすべて返します。B内に一致する行を持たないA内のすべての行に対し、Bの列を含む選択リストの式にはデータベースによりnullが返されます。
表AおよびBの右外部結合を実行する問合せでは、B内の行をすべて返します。A内に一致する行を持たないB内のすべての行に対し、Aの列を含む選択リストの式にはデータベースによりnullが返されます。
結合式で問合せを行うと、EclipseLinkは結合を使用して、他のオブジェクトの値、または同じオブジェクトの一部を表す他の表の値をチェックすることができます。これはほとんどの状況でうまくいきますが、リレーションシップの一方が存在しない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"))
外部結合のサポートと構文は、データベースとデータベース・ドライバによって大きく異なります。EclipseLinkでは、ほとんどのデータベースの外部結合がサポートされています。
結合は、選択基準、順序付け、レポート問合せ、部分オブジェクト、1対1リレーショナル・マッピング、結合読取りなど、式が使用されている任意の場所で使用できます。
表10-1に示すExpression APIを使用して、内部および外部結合式を構成します。
表10-1 結合用のExpression API
Expression API | 結合のタイプ | マッピングのタイプ |
---|---|---|
|
内部 |
1対1 |
|
外部 |
1対1 |
|
内部 |
1対多、多対多 |
|
外部 |
1対多、多対多 |
1対多または多対多のリレーションシップに対して問合せを行うには、anyOf
操作を使用します。その名前が示すように、この操作では問合せ基準を満たすリレーションシップの多くの側面ですべての項目を返す問合せがサポートされます。