4.2. エンティティ Bean (Java Persistence API)
EJB3 セッション bean により、データを実装しトランザクションメソッドでビジネスロジックにアクセスできるようになります。実際データベースにアクセスするには、EJB3 エンティティ bean とエンティティマネージャー API が必要です。これらはまとめて、Java Persistence API (JPA) と呼ばれています。
EJB3 エンティティ Bean は Plain Old Java Object (POJO) で、関係データベースのテーブルにマッピングします。例えば、以下のエンティティ bean クラスは、Customer という名前の関係テーブルにマッピングします。このテーブルには、name、age、singupdate の3つカラムがあり、bean の各インスタンスは、テーブルの各行に対応します。
@Entity
public class Customer {
String name;
public String getName () {
return name;
}
public void setName (String name) {
this.name = name;
}
int age;
public int getAge () {
return age;
}
public void setAge (int age) {
this.age = age;
}
Date signupdate;
public Date getSignupdate () {
return signupdate;
}
public void setSignupdate (Date signupdate) {
this.signupdate = signupdate;
}
}
単純なデータプロパティ以外に、エンティティ bean には@OneToOne、@OneToMany、@ManyToMany などの関係マッピングアノテーションを持つ、その他のエンティティ bean への参照も含むことができます。これらのエンティティオブジェクトの関係は、自動的に外部キーとしてデータベース内に設定されます。例えば、以下の例では Customer テーブル内の各レコードには該当するレコードが Account テーブルに1つ、Order テーブルに複数あり、Employee テーブルの各レコードには、該当するレコードが Customer テーブルに複数存在します。
@Entity
public class Customer {
... ...
Account account;
@OneToOne
public Account getAccount () {
return account;
}
public void setAccount (Accout account) {
this.account = account;
}
Employee salesRep;
@ManyToOne
public Employee getSalesRep () {
return salesRep;
}
public void setSalesRep (Employee salesRep) {
this.salesRep = salesRep;
}
Vector <Order> orders;
@OneToMany
public Vector <Order> getOrders () {
return orders;
}
public void setOrders (Vector <Order> orders) {
this.orders = orders;
}
EntityManager API を使い、エンティティ bean の作成、更新、削除、クエリを行うことができます。EntityManager はプロセス中に基盤のデータベーステーブルを透過的に更新します。@PersistenceContext アノテーションを使い EJB セッション bean で EntityManager オブジェクトを取得することができます。
@PersistenceContext
EntityManager em;
Customer customer = new Customer ();
// populate data in customer
// Save the newly created customer object to DB
em.persist (customer);
// Increase age by 1 and auto save to database
customer.setAge (customer.getAge() + 1);
// delete the customer and its related objects from the DB
em.remove (customer);
// Get all customer records with age > 30 from the DB
List <Customer> customers = em.query (
"select c from Customer where c.age > 30");
EntityManager API の詳細用途に関しては、本書の対象外となっています。興味のある方は、JPA 文書あるいは Hibernate EntityManager の文書を参照してください。
4.2.1. persistence.xml ファイル
EntityManager API は優れていますが、サーバーはエンティティオブジェクトを保存、更新、クエリすべきデータベースがどれなのか、どのように把握するのでしょうか?性能や問題解決を向上できるように、基盤となる object-relational-mapping エンジンやキャッシュをどのように設定したらいいでしょう。persistence.xml ファイルで、EntityManager を自由自在に設定することができます。
persistence.xml ファイルは、JPA の標準設定ファイルです。このファイルは、エンティティ bean を含む JAR ファイルの META-INF ディレクトリに入れる必要があります。persistence.xml ファイルは、persistence-unit をスコープ化された現在の classloader 内に一意の名前で定義する必要があります。プロバイダー属性は、基盤となる JPA EntityManager 実装を指定します。JBoss Enterprise Application Platform では、デフォルトの JPA プロバイダーは、Hibernate で唯一対応で推奨しているプロバイダーです。jta-data-source は、この永続ユニットのマッピング先のデータベースの JNDI 名を参照します。ここでは、java:/DefaultDS は、JBoss Enterprise Application Platform に埋め込まれている HSQL DB を参照しています。JBoss AS 用に別のデータベースを設定する方法は、14章JBoss Enterprise Application Platform で別のデータベースを使用 を参照してください。
<persistence>
<persistence-unit name="myapp">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
... ...
</properties>
</persistence-unit>
</persistence>
注記
永続ユニットのインスタンスが複数、同じアプリケーションで定義されている可能性があるため、通常 @PersistenceContext アノテーションに対して明示的にどのユニットを注入したいかを指示する必要があります。例えば、@PersistenceContext(name="myapp\") は、myapp という名前の永続ユニットから EntityManager を注入します。
しかし、スコープ設定された独自のクラスローダーに EAR アプリケーションをデプロイし、全アプリケーションで1つの永続ユニットのみ定義されている場合、 @PersistenceContextの "name" を省略可能です。EAR パッケージとデプロイメントについては、本章で後述していますのでそちらを参照してください。
persistence.xml のプロパティ要素には、基盤永続プロバイダー向けの設定プロパティを含めることができます。JBoss Enterprise Application Platform は Hibernate を EJB3 永続プロバイダーとして利用するため、Hibernate オプションをここで渡すことができます。詳細については、Hibernate と Hibernate EntityManager 文書を参照してください。ここでは、永続エンジンの SQL 方言を HSQL に設定し、アプリケーション起動時にエンティティ bean からテーブルを作成し、アプリケーション停止時にこのテーブルを破棄するという例を提示しているだけです。
<persistence>
<persistence-unit name="myapp">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>