30.6.6. DeclaredSQL

DeclaredSQL は旧 JAWS CMP 1.1 エンジンの finder 宣言をベースにしていますが、CMP 2.0 用にアップデートされています。通常、この宣言を使い、EJB-QL や JBossQL では表示できない WHERE 句を使ったクエリを制限しています。declared-sql 要素のコンテンツモデルは 図30.12「jbosscmp-jdbc declared-sql 要素のコンテンツモデル」に示しています。
jbosscmp-jdbc declared-sql 要素のコンテンツモデル

図30.12 jbosscmp-jdbc declared-sql 要素のコンテンツモデル

  • select: select 要素は選択する対象を指定するもので、以下の要素で構成されています。
    • distinct:この空の要素がある場合、JBoss は DISTINCT キーワードを追加して SELECT 句を生成します。デフォルトでは、メソッドが java.util.Set を返した場合、DISTINCT を使用するように設定されています。
    • ejb-name: 選択するエンティティの ejb-name を示します。この項目は、クエリーが select メソッドの場合のみ必須です。
    • field-name: 指定したエンティティから選択される CMP フィールドの名称です。デフォルトではエンティティ全体を選択するよう設定されています。
    • alias: メインの select テーブルに使用するエイリアスを指定します。デフォルトは ejb-name を使用します。
    • additional-columns: finder で任意のカラムの命令を実行、あるいは select の集約関数に対応するために選択されるカラムを宣言します。
  • from: from 要素は、生成済みの FROM 句に追加する SQL を宣言します。
  • where: where 要素は クエリー用の WHERE 句を宣言します。
  • order: order 要素はクエリー用の ORDER 句を宣言します。
  • other: other 要素はクエリーの最後に追加する SQL を宣言します。
DeclaredSQL 宣言の例を以下に示します。
<jbosscmp-jdbc>
    <enterprise-beans>
        <entity>
            <ejb-name>GangsterEJB</ejb-name>
            <query>
                <query-method>
                    <method-name>findBadDudes_declaredsql</method-name>
                    <method-params>
                        <method-param>int</method-param>
                    </method-params>
                </query-method>
                <declared-sql>
                    <where><![CDATA[ badness > {0} ]]></where>
                    <order><![CDATA[ badness DESC ]]></order>
                </declared-sql>
            </query>
        </entity>
    </enterprise-beans>
</jbosscmp-jdbc>
生成される SQL は次のようになります。
SELECT id
FROM gangster
WHERE badness > ?
ORDER BY badness DESC
ご覧のように、JBoss はこのエンティティにプライマリキーを選択するのに必要な SELECT および FROM 句を生成します。ご希望であれば、自動生成された FROM 句の末尾に追加される FROM 句を指定することができます。以下に FROM 句を追加した DeclaredSQL 宣言の例を示します。
<jbosscmp-jdbc>
    <enterprise-beans>
        <entity>
            <ejb-name>GangsterEJB</ejb-name>
            <query>
                <query-method>
                    <method-name>ejbSelectBoss_declaredsql</method-name>
                    <method-params>
                        <method-param>java.lang.String</method-param>
                    </method-params>
                </query-method>
                <declared-sql>
                    <select>
                        <distinct/>
                        <ejb-name>GangsterEJB</ejb-name>
                        <alias>boss</alias>
                    </select>
                    <from><![CDATA[, gangster g, organization o]]></from>
                    <where><![CDATA[
                     (LCASE(g.name) = {0} OR LCASE(g.nick_name) = {0}) AND
                     g.organization = o.name AND o.the_boss = boss.id
                     ]]></where>
                </declared-sql>
            </query>
        </entity>
    </enterprise-beans>
</jbosscmp-jdbc>
生成される SQL は次のようになります。
SELECT DISTINCT boss.id
    FROM gangster boss, gangster g, organization o
    WHERE (LCASE(g.name) = ? OR LCASE(g.nick_name) = ?) AND
          g.organization = o.name AND o.the_boss = boss.id
FROM 句はコンマで始まりますので注意してください。これは、コンテナーが生成された FROM 句の末尾に宣言した FROM 句を追加するためです。FROM 句は SQL JOIN ステートメントで始まる場合もあります。select メソッドなので、選択されるエンティティを宣言する select要素が必要です。エイリアスもクエリに対して宣言されますので、注意してください。エイリアスが宣言されない場合、table-name をエイリアスとして使用します。つまり、SELECT 句が table_name.field_nameスタイルのカラム宣言になります。データベースベンダーによってはこの構文をサポートしていませんので、エイリアスの宣言を推奨します。任意でdistinct 要素により SELECT 句は SELECT DISTINCT 宣言を使用します。DeclaredSQL 宣言は CMP フィールドを選択する select メソッドでも使用することができます。
ここで Organization が運営している場所の郵便番号を返す select をオーバーライドする場合の例を以下に示します。
<jbosscmp-jdbc>
    <enterprise-beans>
        <entity>
            <ejb-name>OrganizationEJB</ejb-name>
            <query>
                <query-method>
                    <method-name>ejbSelectOperatingZipCodes_declaredsql</method-name>
                    <method-params>
                        <method-param>java.lang.String</method-param>
                    </method-params>
                </query-method>
                <declared-sql> <select> <distinct/> <ejb-name>LocationEJB</ejb-name> <field-name>zipCode</field-name> <alias>hangout</alias> </select> <from><![CDATA[ , organization o, gangster g ]]></from> <where><![CDATA[ LCASE(o.name) = {0} AND o.name = g.organization AND g.hangout = hangout.id ]]></where> <order><![CDATA[ hangout.zip ]]></order> </declared-sql>
            </query>
        </entity>
    </enterprise-beans>
</jbosscmp-jdbc>
対応する SQL は次のようになります。
SELECT DISTINCT hangout.zip
    FROM location hangout, organization o, gangster g
    WHERE LCASE(o.name) = ? AND o.name = g.organization AND g.hangout = hangout.id
                ORDER BY hangout.zip

30.6.6.1. パラメーター

DeclaredSQL はまったく新しいパラメーター処理システムを採用し、エンティティと DVC パラメーターをサポートします。パラメーターは中括弧に入れ、1 ベースの EJB-QL パラメーターとは別の 0 ベースのインデックスを使用します。パラメーターには以下の 3 種類のカテゴリがあります。Simple、DVC と entity です。
  • simple: シンプルパラメーターは既知(マッピング済みの)DVC やエンティティ以外のあらゆるタイプを指します。シンプルパラメーターは {0} などの引数のみを含みます。シンプルパラメーターが設定されている場合、パラメーターを設定する JDBC タイプは、エンティティに対する datasourcemapping で決定します。未知の DVC はシリアル化され、パラメーターとして設定されます。WHERE 句では BLOB 値の使用をサポートしていないデータベースがほとんどですので、注意してください。
  • DVC: DVC パラメーターは既知の(マッピング済み)DVC になります。DVC パラメーターはシンプルプロパティ(別の DVC ではないもの)を逆参照する必要があります。たとえば、タイプContactInfoの CVS プロパティがある場合、有効なパラメーターの宣言は{0.email} および {0.cell.areaCode} になり、{0.cell} にはなりません。パラメーターの設定に使用する JDBC タイプは、プロパティのクラスタイプとエンティティの datasourcemapping により決まります。パラメーターの設定に使用する JDBC タイプは、dependent-value-class 要素でこのプロパティに対して宣言した JDBC タイプになります。
  • entity: エンティティパラメーターは、アプリケーションにある任意のエンティティになります。エンティティパラメーターは、DVC プライマリキーフィールドのシンプルプライマリキーフィールド、またはシンプルプロパティを逆参照する必要があります。たとえば、タイプ Gangsterのパラメーターがある場合、有効なパラメーター宣言は {0.gangsterId}になります。タイプ ContactInfoのプライマリキーフィールドの名前が付いたエンティティがある場合、 valid parameter 宣言は {0.info.cell.areaCode}になります。エンティティのプライマリキーの構成要素であるフィールドのみ逆参照できます(今後のバージョンではこの制限がなくなる予定です)。パラメーターの設定に使用する JDBC タイプは、エンティティ宣言でこのフィールドに対して宣言した JDBC タイプになります。