エンティティBeanを移行する
次に、EJB 2.1のエンティティBeanをEJB 3.0仕様に移行する方法を説明します。EJB 2.1のエンティティBeanは、EntityBeanインターフェイスを実装し、getter CMPフィールドメソッド、setter CMPフィールドメソッド、getter CMRフィールドメソッド、setter CMRフィールドメソッド、コールバックメソッド、およびejbCreate/ejbPostCreateメソッドから成り立ちます。サンプルエンティティBeanである「BookCatalogBean.java」(リスト1)は、CMPフィールドのtitle、author、およびpublisherと、CMRフィールドのeditionsから成り立ちます。
import javax.ejb.EntityBean; import javax.ejb.EntityContext; public class BookCatalogBean implements EntityBean { private EntityContext ctx; public abstract void setTitle(); public abstract String getTitle(); public abstract void setAuthor(); public abstract String getAuthor(); public abstract void setPublisher(); public abstract String getPublisher(); public abstract void setEditions( java.util.Collection editions); public abstract java.util.Collection getEditions(); public String ejbCreate(String title) { setTitle(title); return null; } public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void ejbLoad() {} public void ejbStore() {} public void setEntityContext(EntityContext ctx) { this.ctx=ctx; } public void unsetEntityContext() { ctx = null; } }
このEJB 2.1のエンティティBeanの「ejb-jar.xml」配備記述子(リスト2)では、EJBのクラスとインターフェイス、CMPフィールド、EJB QLクエリ、およびCMRリレーションシップを指定します。BookCatalogBeanエンティティBeanでは、finderメソッドのfindByTitle()とCMRフィールドのeditionsを定義します。
<?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <entity> <ejb-name>BookCatalog</ejb-name> <local-home>BookCatalogLocalHome</local-home> <local>BookCatalogLocal</local> <ejb-class>BookCatalogBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>String</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>BookCatalog</abstract-schema-name> <cmp-field> <field-name>title</field-name> </cmp-field> <cmp-field> <field-name>author</field-name> </cmp-field> <cmp-field> <field-name>publisher</field-name> </cmp-field> <query> <query-method> <method-name>findByTitle</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT DISTINCT OBJECT(obj) FROM BookCatalog obj WHERE obj.title = ?1 ]]> </ejb-ql> </query> </entity> </enterprise-beans> <relationships> <ejb-relation> <ejb-relation-name>BookCatalog-Editions</ejb-relation-name> <ejb-relationship-role> <ejb-relationship-role-name> BookCatalog-Has-Editions </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>BookCatalog</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>editions</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field> </ejb-relationship-role> <ejb-relationship-role> <ejb-relationship-role-name> Editions-Belong-To-BookCatalog </ejb-relationship-role-name> <multiplicity>One</multiplicity> <cascade-delete /> <relationship-role-source> <ejb-name>Edition</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation> </relationships> </ejb-jar>
一方、EJB 2.1のBeanクラスに対応するEJB 3.0のエンティティBeanクラスはPOJOで、かなり簡潔化されています(リスト3)。
import javax.persistence.Entity; import javax.persistence.NamedQuery; import javax.persistence.Id; import javax.persistence.Column; import javax.persistence.OneToMany; @Entity @NamedQuery(name="findByTitle", queryString = "SELECT DISTINCT OBJECT(obj) FROM BookCatalog obj WHERE obj.title = ?1") public class BookCatalogBean { public BookCatalogBean(){} public BookCatalogBean(String title) { this.title=title; } private String title; private String author; private String publisher; @Id @Column(name="title", primaryKey="true") public String getTitle(){return title;} public void setTitle(){this.title=title;} public void setAuthor(String author){this.author=author;} public String getAuthor(){return author;} public void setPublisher(String publisher) { this.publisher=publisher; } public String getPublisher(){return publisher;} private java.util.Collection<Edition> editions; @OneToMany public void setEditions( java.util.Collection editions) { this.editions=editions; } public java.util.Collection getEditions(){return editions;} }
このBeanクラスのEJB 3.0バージョンでは、メタデータアノテーションの@Entityを使います。finderメソッドは、EJB 2.1では配備記述子「ejb-jar.xml」ファイルで要素を使って指定しますが、EJB 3.0では@NamedQueriesアノテーションと@NamedQueryアノテーションを使って指定します。CMRリレーションシップは、EJB 2.1では「ejb-jar.xml」ファイルで要素を使って指定しますが、EJB 3.0ではメタデータアノテーションを使って指定します。主キーフィールドは、アノテーション@Idを使って指定します。表1に、EJB 3.0のよく使われるメタデータアノテーションと、アノテーションの影響を受ける要素(該当する場合)を示します。
| アノテーション | 説明 | アノテーションの要素 |
@Entity | エンティティBeanクラスのアノテーションを付けます。 | |
@Table | エンティティBeanテーブルのアノテーションを付けます。@Tableを指定しないと、既定でテーブル名はEJB名になります。 | name、schema |
@Id | 主キープロパティまたはフィールドのアノテーションを付けます。 | |
@Transient | 非永続プロパティまたはフィールドのアノテーションを付けます。 | |
@Column | エンティティBeanの永続プロパティのマップ列にアノテーションを付けます。 | name、primaryKey、nullable、length。既定ではプロパティ名またはフィールド名です。 |
@NamedQueries | 名前付きクエリのグループにアノテーションを付けます。 | |
@NamedQuery | 名前付きクエリまたはfinderメソッドに関連付けられたクエリにアノテーションを付けます。 | name、queryString |
@OneToMany | 1対多の関連付けにアノテーションを付けます。 | Cascade |
@OneToOne | 1対1の関連付けにアノテーションを付けます。 | Cascade |
@ManyToMany | 多対多の関連付けにアノテーションを付けます。 | Cascade |
@ManyToOne | 多対1の関連付けにアノテーションを付けます。 | Cascade |
EJB 3.0では、EJB 2.1のエンティティBeanクラスのfinderメソッドfindByTitle()に対応するアノテーションとして、@NamedQueryアノテーションを使います。また、EJB 2.1のエンティティBeanのCMRリレーションシップBookCatalog-Editionsに対応するアノテーションとして、EJB 3.0では@OneToManyアノテーションを使います。@Idアノテーションで、IDプロパティtitleにアノテーションを付けます。@Columnアノテーションで、IDプロパティtitleに対応するデータベース列を指定します。@Columnアノテーションを使ってエンティティBeanの永続プロパティにアノテーションが付けられていない場合、EJBサーバーは、列名はエンティティBeanのプロパティ名と同じであると見なします。エンティティBeanの非永続プロパティには、@Transientアノテーションを使ってアノテーションを付けます。
