Oracle® Fusion Middleware Oracle WebLogic Server エンタープライズ JavaBeans (EJB) プログラマーズ ガイド 11g リリース 1 (10.3.1) B55528-01 |
|
戻る |
EJB クエリ言語 (EJB QL) は、コンテナ管理による永続性を利用する 2.0 エンティティ EJB のファインダ メソッドを定義する移植可能なクエリ言語です。このクエリ言語は SQL に似ており、クエリ内の 1 つまたは複数のエンティティ EJB オブジェクトまたはフィールドを選択する場合に使用します。findByPrimaryKey()
以外のすべてのファインダ メソッドのクエリをデプロイメント記述子で作成できます。findByPrimaryKey
は、EJB コンテナで自動的に処理されます。
以下の節では、EJB QL について説明します。
デプロイメント記述子では、EJB QL クエリ文字列を使用して、EJB 2.x のエンティティ Bean の各ファインダ クエリを定義する必要があります。WebLogic Query Language (WLQL) を EJB 2.x エンティティ Bean で使用することはできません。WLQL は、EJB 1.1 のコンテナ管理による永続性で使用することを想定しています。WLQL および EJB 1.1 のコンテナ管理による永続性の詳細については、「EJB 1.1 CMP 用の WebLogic クエリ言語 (WLQL) の使用」を参照してください。
WebLogic Server には、標準の EJB QL の拡張であり、SQL に似た WebLogic QL という言語が用意されています。query
は、weblogic-ql
要素を使用して、weblogic-cmp-jar.xml
デプロイメント記述子に定義します。
ejb-jar.xml
ファイルには、weblogic-cmp-jar.xml
ファイルの weblogic-ql
要素に対応するクエリ要素が必要です。ただし、weblogic-cmp-jar.xml
のクエリ要素の値は、ejb-jar.xml
のクエリ要素の値をオーバーライドします。
以下のトピックでは、EJB 2.x QL の WebLogic QL 拡張機能を使用する際のガイドラインを示します。
EJB WebLogic QL upper
および lower
拡張機能は、大文字と小文字の違いがある以外は検索式の文字と一致する結果をファインダ メソッドが返せるように、引数の大文字と小文字を変換します。大文字と小文字の変換は文字列を照合するための一時的なものなので、データベース内に永続しません。基底のデータベースも、upper
および lower
関数をサポートしている必要があります。
upper
関数は、文字列の照合の前に、引数内の文字をすべて大文字に変換します。クエリ内で大文字で表された式で upper
関数を使用すると、大文字であるか小文字であるかに関係なく、式に一致するすべての項目が返されます。次に例を示します。
select name from products where upper(name)='DETERGENT';
lower
関数は、文字列の照合の前に、引数内の文字をすべて小文字に変換します。クエリ内で小文字で表された式で lower
関数を使用すると、大文字であるか小文字であるかに関係なく、式に一致するすべての項目が返されます。
select type from products where lower(name)='domestic';
EJB QL の ORDER BY
句は、Finder
メソッドと連携して、選択における CMP フィールドの選択順序を指定するキーワードです。
WebLogic Server では、EJB QL のサブクエリの次のような機能をサポートしています。
サブクエリの戻り値の型
単一の cmp-field
集約関数
単純主キーを持つ Bean
比較オペランドとしてのサブクエリ
相関サブクエリ
非相関サブクエリ
サブクエリでの DISTINCT
句
WebLogic QL とサブクエリの関係は、SQL クエリとサブクエリの関係に似ています。WebLogic QL のサブクエリは、外部 WebLogic QL クエリの WHERE
句内で使用してください。若干の例外はありますが、サブクエリの構文は WebLogic QL クエリのものとほぼ同じです。
WebLogic QL を指定する手順については、「EJB QL の EJB 2.x WebLogic QL 拡張機能の使い方」を参照してください。この手順に従って、SELECT
文で次の例のようにサブクエリを指定します。
次のクエリは、成績順位をもとに平均以上の生徒を選択しています。
SELECT OBJECT(s) FROM studentBean AS s WHERE s.grade > (SELECT AVG(s2.grade) FROM StudentBean AS s2)
注意 : 上記クエリの例で、サブクエリ「SELECT AVG(s2.grade) FROM StudentBean AS s2」の構文は EJB QL クエリと同じです。 |
サブクエリをネストすることもできます。この深さは、基底のデータベースのネストの許容範囲によって制限されます。
WebLogic QL クエリでは、メイン クエリとそのすべてのサブクエリの FROM
句で宣言される識別子がユニークでなければなりません。これはつまり、サブクエリの内側で前にローカルに宣言した識別子をそのサブクエリで再び宣言することはできないということです。
たとえば、次の例は無効です。EmployeeBean
がクエリとサブクエリの双方で emp として宣言されています。
SELECT OBJECT(emp) FROM EmployeeBean As emp WHERE emp.salary=(SELECT MAX(emp.salary) FROM EmployeeBean AS emp WHERE employee.state=MA)
このクエリは次のように記述すべきです。
SELECT OBJECT(emp) FROM EmployeeBean As emp WHERE emp.salary=(SELECT MAX(emp2.salary) FROM EmployeeBean AS emp2 WHERE emp2.state=MA)
この例では、サブクエリの Employee Bean がメインクエリの Employee Bean と異なる識別子になるように正しく宣言されています。
WebLogic QL サブクエリの戻り値の型は、次のような各種の型のいずれかになります。
単一の cmp-field 型のサブクエリ
WebLogic Server は、cmp-field
で構成されている戻り値型をサポートしています。サブクエリから返される結果は、1 つの値または値の集合から構成されている可能性があります。cmp-field
型の値を返すサブクエリの例を次に示します。
SELECT emp.salary FROM EmployeeBean AS emp WHERE emp.dept = 'finance'
このサブクエリは、財務部門の従業員の給料すべてを選択しています。
集約関数
WebLogic Server は、ある cmp-field
に対する集約から構成されている戻り値型をサポートしています。集約は必ず 1 つの値から構成されるので、ここで返される値も常に 1 つの値になります。cmp-field
の集約 (MAX
) の型の値を返すサブクエリの例を次に示します。
SELECT MAX(emp.salary) FROM EmployeeBean AS emp WHERE emp.state=MA
このサブクエリは、マサチューセッツで最高額の給料を 1 つだけ選択しています。
集約関数の詳細については、「集約関数の使用」を参照してください。
単純主キーを持つ Bean
WebLogic Server は、単純主キーを持つ 1 つの cmp-bean
で構成されている戻り値型をサポートしています。
単純主キーを持つ Bean 型の値を返すサブクエリの例を次に示します。
SELECT OBJECT(emp) FROM EMployeeBean As emp WHERE emp.department.budget>1,000,000
このサブクエリは、$1,000,000 以上の予算がある部門の全従業員のリストを返します。
注意 : 複合主キーを持つ Bean はサポートされていません。複合主キーを持つ Bean をサブクエリの戻り値の型として指定しようとしても、クエリをコンパイルする時点で失敗に終わります。 |
サブクエリを比較演算子および算術演算子のオペランドとして使用します。WebLogic QL では、以下の演算子のオペランドとしてサブクエリをサポートしています。
比較演算子 ([NOT]IN, [NOT]EXISTS
)
および
算術演算子 (<、>、<=、>=、=、および該当部分すべてを表す <>
)
[NOT]IN
[NOT]IN
比較演算子は、左側のオペランドが右側のサブクエリ オペランドのメンバーかどうか検査します。
サブクエリが NOT IN
オペレータの右側のオペランドとなっている例を次に示します。
SELECT OBJECT(item) FROM ItemBean AS item WHERE item.itemId NOT IN (SELECT oItem2.item.itemID FROM OrderBean AS orders2, IN(orders2.orderItems)oIttem2
サブクエリは、すべての注文から品目すべてを選択しています。
メイン クエリの NOT IN
演算子では、サブクエリによって返された集合の中に含まれていない品目すべてを選択しています。したがって、最終的に、メインクエリが未注文の品目すべてを選択します。
[NOT]EXISTS
[NOT]EXISTS
比較演算子は、サブクエリ オペランドによって返された集合が空かどうか検査します。
サブクエリが NOT EXISTS
オペランドのオペランドとなっている例を次に示します。
SELECT (cust) FROM CustomerBean AS cust WHERE NOT EXISTS (SELECT order.cust_num FROM OrderBean AS order WHERE cust.num=order_num)
これは、相関サブクエリを用いたクエリの一例となっています。詳細については「相関サブクエリと非相関サブクエリ」を参照してください。次のクエリは、注文していない顧客をすべて返します。
SELECT (cust) FROM CustomerBean AS cust WHERE cust.num NOT IN (SELECT order.cust_num FROM OrderBean AS order WHERE cust.num=order_num)
算術演算子
右側のサブクエリ オペランドが 1 つの値を返す場合、比較の算術演算子を使用できます。右側のサブクエリが複数の値を返す場合には、サブクエリの前に ANY
または ALL
修飾子が必要です。
「=」演算子を使用したサブクエリの例を次に示します。
SELECT OBJECT (order) FROM OrderBean AS order, IN(order.orderItems)oItem WHERE oItem.quantityOrdered = (SELECT MAX (subOItem.quantityOrdered) FROM Order ItemBean AS subOItem WHERE subOItem,item itemID = ?1) AND oItem.item.itemId = ?1
特定の itemId
に対し、サブクエリはその品目の注文の最高数を返します。サブクエリが返している集合が、「=」演算子に必要な 1 つの値となっている点に注意してください。
メイン クエリの「=
」演算子では、これと同じ品目 ID に対し、どの注文の注文品目の注文量がサブクエリから返された注文の最高数に等しいかを調べています。最終的に、特定の品目について注文が最高数である OrderBean をクエリが返します。
右側のサブクエリ オペラントが複数の値を返す場合には、算術演算子と ANY
または ALL
と組み合わせて使用します。
ANY
または ALL
を使用したサブクエリの例を次に示します。
SELECT OBJECT (order) FROM OrderBean AS order, IN(order.orderItems)oItem WHERE oItem.quantityOrdered > ALL (SELECT subOItem.quantityOrdered FROM OrderBean AS suborder IN (subOrder.orderItems)subOItem WHERE subOrder,orderId = ?1)
サブクエリは、特定の注文 ID に対し、その注文 ID で注文された各品目の注文数の集合を返します。メイン クエリの「>」
ALL
演算子は、各品目の注文数がサブクエリから返された集合内のすべての値を上回っている注文すべてを探しています。最終的にメインクエリは、入力された注文に対して、全品目で注文数を上回っている注文すべてを返します。
注意 : サブクエリが複数の値を持つ結果を返す可能性があるため、「> 」演算子ではなく、「>」ALL 演算子が使用されている点に注意してください。 |
WebLogic Server は、相関サブクエリと非相関サブクエリの双方をサポートしています。
非相関サブクエリ
非相関サブクエリは、その外部クエリとは独立して評価されます。非相関サブクエリの例を次に示します。
SELECT OBJECT(emp) FROM EmployeeBean AS emp WHERE emp.salary> (SELECT AVG(emp2.salary) FROM EmployeeBean AS emp2)
この非相関サブクエリの例では、平均以上の給与の従業員を選択しています。この例では、算術演算子「>」を使用します。
相関サブクエリ
相関サブクエリは、その外部クエリの値がサブクエリでの評価に関与するサブクエリです。相関サブクエリの例を次に示します。
SELECT OBJECT (mainOrder) FROM OrderBean AS mainOrder WHERE 10> (SELECT COUNT (DISTINCT subOrder.ship_date) FROM OrderBean AS subOrder WHERE subOrder.ship_date>mainOrder.ship_date AND mainOrder.ship_date IS NOT NULL
この相関サブクエリの例では、最後に出荷された 10 個の注文を選択しています。NOT IN
演算子を使用しています。
注意 : 相関クエリでは、非相関クエリより処理オーバーヘッドが大きくなる可能性があることに注意してください。 |
サブクエリ内で DISTINCT
句を使用すると、そのサブクエリで生成される SELECT DISTINCT
内で SQL SELECT DISTINCT を使うことができます。サブクエリでの DISTINCT
句の使い方は、メインクエリでの使い方とは異なります。メインクエリ内の DISTINCT
句は EJB コンテナによって施されますが、サブクエリ内の DISTINCT
句は生成された SQL の SQL SELECT DISTINCT
によって施されます。サブクエリの DISTINCT
句の例を示します。
SELECT OBJECT (mainOrder) FROM OrderBean AS mainOrder WHERE 10> (SELECT COUNT (DISTINCT subOrder.ship_date) FROM OrderBean AS subOrder WHERE subOrder.ship_date>mainOrder.ship_date AND mainOrder.ship_date IS NOT NULL
WebLogic Server では、WebLogic QL の算術関数をサポートしています。WebLogic QL を指定する手順については、「EJB QL の EJB 2.x WebLogic QL 拡張機能の使い方」を参照してください。これらの例は、算術関数を指定する SELECT 文で使用します。
表 G-1 算術関数
算術関数 | 説明 |
---|---|
|
数値 (int、double、float) の絶対値を返す。 |
|
|
|
平方根を返す。 |
注意 : EJB QL 算術関数は、DB2 ではクエリ パラメータと一緒に使用できません。 |
WebLogic Server では、WebLogic QL の集約関数をサポートしています。これらは、WHERE
句のようなクエリの一部ではなく、SELECT
句の対象として使われるのみです。集約関数の振る舞いは SQL 関数と似ています。これらの関数は、クエリの WHERE
条件によって返される Bean の外側で評価されます。
WebLogic QL を指定する手順については、「EJB QL の EJB 2.x WebLogic QL 拡張機能の使い方」を参照してください。これに従って、次の表のサンプルのように、集約関数を指定した SELECT 文を記述します。
サポートされている関数とサンプル文のリストを次に示します。
表 G-2 集約関数
集約関数 | 有効な引数データ型 | 説明 | サンプル文 |
---|---|---|---|
|
|
このフィールドの最小値を返す。 |
この文では、入力された特定のサイズの最安値を選択している。 |
|
|
このフィールドの最大値を返す。 |
この文では、ロサンゼルス市内の販売代理人それぞれが担当する顧客数の中の最大値を選択している。 |
|
numeric |
このフィールドの平均値を返す。 |
この文では、コンピュータ科学分野の書籍の平均価格を選択している。 |
|
numeric |
このフィールドの合計を返す。 |
この文では、ロサンゼルス市内の販売代理人が担当している顧客の合計数を取得している。 |
|
numeric |
フィールドの発生数を返す。 |
この文では、100 万ドル以上の非公開取引の数を取得している。 |
注意 : このリリースの WebLogic Server では、以下の条件がすべて真の場合、ObjectNotFoundException が返されます。
|
SQL 仕様では、集約と共に個々のフィールドを選択するクエリには GROUP BY
句を指定する必要があります。
次の手順で、ResultSet として集約関数を返すことができます。
WebLogic Server は、複数カラム クエリの結果を java.sql.ResultSet
の形式で返す、ejbSelect()
クエリをサポートしています。この機能をサポートするために、WebLogic Server では、次のように SELECT
句の対象フィールドをカンマで区切って指定できるようになりました。
SELECT emmp.name, emp.zip FROM EmployeeBean AS emp
このクエリは、従業員の名前と郵便番号の値をカラムとしその数行を含んだ java.sqlResultSet
を返します。
WebLogic QL を指定する手順については、「EJB QL の EJB 2.x WebLogic QL 拡張機能の使い方」を参照してください。この手順に従って、上に示したクエリのように ResultSet を指定します。また、同様にこれに従って、下記の表のサンプルで示すように、集約クエリを指定した SELECT 文を記述します。
EJB QL で作成される ResultSet は、cmp-field
の値、または、cmp-field
値の集合だけを返します。Bean を返すことはできません。
さらに、cmp-field
と集約関数を組み合わせた場合、下記のサンプルに示すような強力なクエリを作成できます。
次の行 (Bean) は、各地区の従業員の給与を示しています。
注意 : 各行が 1 つの Bean を表します。 |
次の SELECT
文のクエリでは、ResultSet、集約関数 (AVG
) と共に GROUP BY
文と ORDER BY
文を使用し、複数カラム クエリの結果を降順ソートを使って取り出します。
SELECT e.location, AVG(e.salary)
FROM Finder EmployeeBean AS e
GROUP BY e.location
ORDER BY 2 DESC
このクエリは、各地区の従業員の平均給与を降順で示します。2 という数字は、ORDER BY
ソートを SELECT
文の 2 番目の項目で実行することを意味しています。GROUP BY
句は、e.location
属性に一致する従業員の平均給与を指定しています。
ResultSet は、次のように降順で並んでいます。
地区 | 平均 |
---|---|
AZ | 100,000 |
CA | 105,000 |
TX | 110,000 |
注意 : ResultSet を返すクエリ内でORDER BY の引数として使用できるのは整数だけです。WebLogic Server では、Bean を返すファインダ、または ejbselect() 内で ORDER BY の引数として整数を使用することはできません。 |
WebLogic Server は、INDEX の使い方に関するヒントを Oracle Query オプティマイザに渡すことを可能にする EJB QL 拡張機能をサポートしています。この拡張機能を使用すると、データベース エンジンにヒントを提供できます。たとえば、検索先のデータベースが ORACLE_SELECT_HINT によって恩恵を受けることがわかっている場合は、ANY 文字列値を取り、その文字列値をデータベースに対するヒントとして SQL SELECT 文の後に挿入する ORACLE_SELECT_HINT 句を定義します。
このオプションを使用するには、この機能を使用するクエリを weblogic-cmp-jar.xml
の weblogic-ql
要素で宣言します。weblogic-ql
要素では、EJB-QL に対する WebLogic 固有の拡張機能を含むクエリを指定します。
WebLogic QL のキーワードおよび使い方は次のとおりです。
SELECT OBJECT(a) FROM BeanA AS a WHERE a.field > 2 ORDER BY a.field SELECT_HINT '/*+ INDEX_ASC(myindex) */'
この文は、Oracle のオプティマイザ ヒントを使用して次の SQL を生成します。
SELECT /*+ INDEX_ASC(myindex) */ column1 FROM ....
WebLogic QL ORACLE_SELECT_HINT 句では、単一引用符で囲まれた部分 (' ') が SQL SELECT の後に挿入されます。クエリ作成者は、引用符内のデータを Oracle データベースが確実に認識できるものにする必要があります。
WebLogic Server では、一連のアクセサ メソッドを使用します。これらのメソッドの名前の先頭には、set と get が付いています。WebLogic Server では、コンテナ管理によるフィールドの読み出しおよび修正にこれらのメソッドを使用します。コンテナによって生成されるこれらのクラスは、「get」または「set」で始まり、ejb-jar.xml
で定義されている永続フィールドの実際の名前を使用する必要があります。また、これらのメソッドは、public
、protected
、および abstract
として宣言します。
Query
インタフェースには、検索と実行の両方のメソッドがあります。検索メソッドは、EJBObjects を返すという点で標準の EJB メソッドと同じように機能します。実行メソッドは、個々のフィールドを選択できるという点でさらに Select
文のように機能します。
Query
インタフェースの戻り値の型は切断された ResultSet
です。つまり、返されたオブジェクトの情報には、ResultSet
がデータベース接続の開いた状態を維持しないことを除いて、ResultSet
の情報にアクセスするのと同じ方法でアクセスします。
Query
インタフェースのプロパティベースのメソッドでは、クエリに固有の設定を指定することができます。QueryProperties
インタフェースは標準の EJB クエリ設定を保持し、WLQueryProperties
インタフェースは WebLogic 固有のクエリ設定を保持します。
Query
インタフェースは QueryProperties
の拡張版ですが、実際の Query
実装は WLQueryProperties
を拡張したものなので、フィールド グループ設定を設定するコード リスト G-3 の例のように安全にキャストできます。
コード リスト G-3 WLQueryProperties でのフィールド グループ設定の設定
Query query=qh.createQuery(); ((WLQueryProperties) query).setFieldGroupName("myGroup"); Collection results=query.find(ejbql);
または
Query query=qh.createQuery(); Properties props = new Properties(); props.setProperty(WLQueryProperties.GROUP_NAME, "myGroup"); Collection results=query.find(ejbql, props);
EJB 1.1 を使用する既存のアプリケーションがある場合、コンテナ管理によるエンティティ EJB ではファインダ メソッド用に WLQL を使用できます。この節では、WLQL の一般的な処理についてのクイック リファレンスを提供します。WLQL の構文と EJB QL の構文の対応については、次の表を参考にしてください。
表 G-6 WLQL から EJB QL への移行
WLQL のサンプル構文 | 対応する EJB QL の構文 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EJB QL クエリに、(明示的クロス積とは対照的な) 暗黙的クロス積が含まれる場合、EJB QL クエリは結果として空の値を返す場合があります。
次のサンプル クエリを検討してください。
SELECT OBJECT(e) FROM EmployeeBean AS e WHERE e.name LIKE 'Joe' OR e.acct.balance < 100
このクエリは AccountEJB
を参照していますが、AccountEJB
は FROM
句にリストされていません。このクエリの結果は、FROM
句に明示的にリストされた AccountEJB
のあるクエリの場合と同じです。
EJB QL のコンパイラ エラー メッセージでは、クエリのどの部分にエラーが生じているのかを特定できるビジュアルな表示が用意され、コンパイルごとに複数のエラーを報告できます。
エラーが報告されると、EJB QL は問題のある場所を記号 =>> <<= で囲んで示します。これらの記号は、次に示すサンプルのコンパイラ エラー報告では赤色で強調されています。
ERROR: Error from appc: Error while reading 'META-INF/FinderEmployeeBeanRDBMS.xml'.The error was:
Query:
EJB Name: FinderEmployeeEJB
Method Name: findThreeLowestSalaryEmployees
Parameter Types: (java.lang.String)
Input EJB Query: SELECT OBJECT(e) FROM FinderEmployeeBean e WHERE f.badField = '2' O
R (e.testId = ?1) ORDER BY e.salary
SELECT OBJECT(e ) FROM FinderEmployeeBean e
WHERE =>> f.badField <<= = '2' OR ( e.testId = ?1 ) ORDER BY e.salary
Invalid Identifier in EJB QL expression:
Problem, the path expression/Identifier 'f.badField' starts with an identifier: 'f'.
The identifier 'f', which can be either a range variable identifier or a collection member identifier, is required to be declared in the FROM clause of its query or in the FROM clause of a parent query.'f' is not defined in the FROM clause of either its query or in any parent query.Action, rewrite the query paying attention to the usage of 'f.badField'.
クエリに複数のエラーが含まれていた場合、EJB QL では、1 回のコンパイル後にこれらのエラーを複数個報告できるようになりました。これまでは、コンパイラが報告できるエラーはコンパイル 1 回につき 1 つだけでした。後続のエラーの報告には、再コンパイルが必要でした。
コンパイラが 1 回のコンパイル後にすべてのエラーを報告する保証はありません。