10 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");
データベース関数および演算子
EclipseLinkでは、様々なデータベースに変換される標準の演算子名を使用して、多くのデータベース関数がサポートされます。
EclipseLinkの演算子は、同等の関数(関数のセット)を持つ任意のデータベースでサポートされます。サポートされるすべての関数と演算子の詳細およびリストは、『Java Persistence API (JPA) Extensions Reference for EclipseLink』の「OPERATOR」および「FUNCTION」を参照してください
注意:
一部の関数はデータベース・プラットフォームに固有です。
演算子は、2つの値を比較する関係演算子です。EclipseLinkの式演算子は、ExpressionOperatorクラスに記載されています。
数値演算関数は、ExpressionMathクラスを通じて使用できます。式における数値演算関数のサポートは、Javaクラスjava.lang.Mathによるサポートに似ています。
Oracle XMLType関数
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メソッドもあります。独自のカスタム関数も作成できます。詳細は、『Java API Reference for EclipseLink』を参照してください。
1対1および集約オブジェクトのリレーションシップを表す式
式には、別の永続クラスとの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では、ほとんどのデータベースの外部結合がサポートされています。
結合でのEclipseLink Expression APIの使用
結合は、選択基準、順序付け、レポート問合せ、部分オブジェクト、1対1リレーショナル・マッピング、結合読取りなど、式が使用されている任意の場所で使用できます。
次の表に示すExpression APIを使用して、内部および外部結合式を構成します。
表10-1 結合用のExpression API
Expression API | 結合のタイプ | マッピングのタイプ |
---|---|---|
get |
内部 |
1対1 |
getAllowingNull |
外部 |
1対1 |
anyOf |
内部 |
1対多、多対多 |
anyOfAllowingNone |
外部 |
1対多、多対多 |
1対多または多対多のリレーションシップに対して問合せを行うには、anyOf操作を使用します。その名前が示すように、この操作では問合せ基準を満たすリレーションシップの多くの側面ですべての項目を返す問合せがサポートされます。