30.4.5. 依存値クラス(DVC: Dependent Value Class)
DVC (dependent value class) とは、文字列や数値など自動認識されるコアタイプ以外の
cmp-field
タイプである Java クラスの識別に使用する用語です。 デフォルトでは、DVC はシリアル化され、シリアル化形式がデータベースの1カラムに格納されます。ここでは説明しませんが、シリアル化形式でのクラスの長期保管には既知の問題がいくつかあります。
JBoss は DVC 内部データを 1つ以上のカラムへ保存することができます。これはレガシーの JavaBean やデータベース構造に対応する場合に便利です。非常にフラットな構造を持つデータベースを検索するのは珍しくありません(
SHIP_LINE1
、SHIP_LINE2
、SHIP_CITY
などのフィールドや請求書送付先の追加フィールドセットを持つ PURCHASE_ORDER
テーブルなど)。この他一般的なデータベース構造としてはエリアコード、外線、内線の別フィールドを持つ電話番号、もしくは複数のフィールドにわたる人名などが挙げられます。DVC では複数のカラムを 1 つの論理フィールドにマッピングすることが可能です。
JBoss は、マッピングされる DVC がシンプルプロパティの JavaBeans ネーミング仕様に準ずること、またデータベース内に格納される各プロパティが getter と setter の両方のメソッドを持っていることが必要となります。さらに、bean は連続化が可能でなければならず、引数なしのコンストラクターを持っていなければなりません。プロパティはシンプルタイプのマッピングされない DVCあるいはマッピングされる DVC のいずれでも構いませんが、EJB にはなれません。DVC マッピングは dependent-value-classes 要素内の dependent-value-class 要素に指定されます。
図30.6 jbosscmp-jdbc dependent-value-class 要素モデル
次にシンプルな
ContactInfo
DVC クラスの例を示します。
public class ContactInfo implements Serializable { /** The cell phone number. */ private PhoneNumber cell; /** The pager number. */ private PhoneNumber pager; /** The email address */ private String email; /** * Creates empty contact info. */ public ContactInfo() { } public PhoneNumber getCell() { return cell; } public void setCell(PhoneNumber cell) { this.cell = cell; } public PhoneNumber getPager() { return pager; } public void setPager(PhoneNumber pager) { this.pager = pager; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email.toLowerCase(); } // ... equals, hashCode, toString }
連絡先情報には電話番号が含まれ、これは別の DVC クラスで表されます。
public class PhoneNumber implements Serializable { /** The first three digits of the phone number. */ private short areaCode; /** The middle three digits of the phone number. */ private short exchange; /** The last four digits of the phone number. */ private short extension; // ... getters and setters // ... equals, hashCode, toString }
これら 2 クラスの DVC マッピングは比較的簡単です。
<dependent-value-classes> <dependent-value-class> <description>A phone number</description> <class>org.jboss.cmp2.crimeportal.PhoneNumber</class> <property> <property-name>areaCode</property-name> <column-name>area_code</column-name> </property> <property> <property-name>exchange</property-name> <column-name>exchange</column-name> </property> <property> <property-name>extension</property-name> <column-name>extension</column-name> </property> </dependent-value-class> <dependent-value-class> <description>General contact info</description> <class>org.jboss.cmp2.crimeportal.ContactInfo</class> <property> <property-name>cell</property-name> <column-name>cell</column-name> </property> <property> <property-name>pager</property-name> <column-name>pager</column-name> </property> <property> <property-name>email</property-name> <column-name>email</column-name> <jdbc-type>VARCHAR</jdbc-type> <sql-type>VARCHAR(128)</sql-type> </property> </dependent-value-class> </dependent-value-classes>
各 DVC は
dependent-value-class
要素で宣言します。DVC は、クラス要素で宣言される Java クラスタイプで識別されます。各プロパティの永続化はプロパティ要素で宣言されます。 この仕様は cmp-field
要素に基づくため、すぐに理解できるようになっています。この制限も今後のリリースでは削除される予定です。現在は、ローカルエンティティの場合はプライマリキーフィールド、リモートエンティティの場合はエンティティハンドルを格納する設定が提案されています。
dependent-value-classes
セクションは内部構造とデフォルトのクラスマッピングを定義します。未知のタイプのフィールドがある場合、JBoss は登録済みの DVC リストを検索します。DVC が見つかったら、カラムセットにこのフィールドを永続化します。それ以外の場合は、単一の列にシリアル化形式で格納されます。JBoss では DVC の継承をサポートしていません。つまり、この検索は宣言タイプのフィールドのみを対象とします。DVC は他の DVC からも構築することができ、JBoss が DVC を発見した場合、DVC ツリー構造をカラムセットにフラット化します。起動時に DVC 回路を発見した場合、JBoss は EJBException
を送出します。プロパティのカラム名はデフォルトでは cmp-field
の後に下線とプロパティのカラム名が付きます。プロパティが DVC の場合、このプロセスが繰り返されます。たとえば、info
とつけられた ContactInfo
を使用する cmp-field
の場合は、
info_cell_area_code info_cell_exchange info_cell_extension info_pager_area_code info_pager_exchange info_pager_extension info_email
自動生成されるカラム名は長すぎる上、認識しにくくなります。カラムのデフォルトマッピングは、以下のようにエンティティ要素でオーバーライド可能です
<jbosscmp-jdbc> <enterprise-beans> <entity> <ejb-name>GangsterEJB</ejb-name> <cmp-field> <field-name>contactInfo</field-name> <property> <property-name>cell.areaCode</property-name> <column-name>cell_area</column-name> </property> <property> <property-name>cell.exchange</property-name> <column-name>cell_exch</column-name> </property> <property> <property-name>cell.extension</property-name> <column-name>cell_ext</column-name> </property> <property> <property-name>pager.areaCode</property-name> <column-name>page_area</column-name> </property> <property> <property-name>pager.exchange</property-name> <column-name>page_exch</column-name> </property> <property> <property-name>pager.extension</property-name> <column-name>page_ext</column-name> </property> <property> <property-name>email</property-name> <column-name>email</column-name> <jdbc-type>VARCHAR</jdbc-type> <sql-type>VARCHAR(128)</sql-type> </property> </cmp-field> </entity> </enterprise-beans> </jbosscmp-jdbc>
エンティティのプロパティ情報をオーバーライドする場合、
cell.areaCode
のようなフラットな観点からプロパティを参照してください。