§Ebean ORM を使う
§Ebean の設定
Play には Ebean ORM が同梱されています。有効にするには、依存性に javaEbean を追加します :
libraryDependencies += javaEbean
その後、以下の行を conf/application.conf
に追加します。
ebean.default="models.*"
ここでは default
データソースを使用する default
Ebean サーバを定義していて、これは適切に設定する必要があります。 ebeanconfig.datasource.default
プロパティを設定することでデフォルトの Ebean サーバの名前を上書きすることもできます。これはテストと開発で別々のデータベースを使いたい場合に便利でしょう。実際のところ、Ebean サーバを必要な数だけ作成し、それぞれのサーバに対するマッパークラスを明示的に定義することができます。
ebean.orders="models.Order,models.OrderItem"
ebean.customers="models.Customer,models.Address"
この例では、2 つの Ebean サーバへのアクセスが設定されています。各サーバはそれぞれ異なるデータベースを使用しています。
(上記した) それぞれの ebean.
設定行は、Ebean が登録することに関心を持つ あらゆる クラス (例えば @Entity
/Model
クラス, @Embeddable
, カスタマイズした ScalarType
と CompoundType
, BeanPersistController
, BeanPersistListener
, BeanFinder
, ServerConfigStartup
, その他) とマッピングすることができます。
根底にある Ebean サーバの設定をカスタマイズするために、conf/ebean.properties
を追加するか、サーバが初期化される前に Ebean の ServerConfig
をプログラムから操作するために ServerConfigStartup
のインスタンスを作成することができます。
例えば、シーケンスのギャップを最小限にするためにシーケンスバッチサイズを減らすと言う、かなり一般的な問題は、以下のようなクラスによって、とてもシンプルに解決することができます。
package models;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.event.ServerConfigStartup;
public class MyServerConfigStartup implements ServerConfigStartup {
@Override
public void onStart(ServerConfig serverConfig) {
serverConfig.setDatabaseSequenceBatchSize(1);
}
}
Ebean は <entity-mappings>
を設定するために (もし存在すれば) conf/orm.xml
ファイルを活用することにも気を付けてください。
Ebean の詳細の情報については、 Ebean ドキュメント をご覧下さい。
§play.db.ebean.Model のスーパークラスを使う
Play は Ebean モデルクラス向けの便利なスーパークラスを定義しています。Play でマップされた典型的な Ebean クラスは以下のようになります。
package models;
import java.util.*;
import javax.persistence.*;
import play.db.ebean.*;
import play.data.format.*;
import play.data.validation.*;
@Entity
public class Task extends Model {
@Id
@Constraints.Min(10)
public Long id;
@Constraints.Required
public String name;
public boolean done;
@Formats.DateTime(pattern="dd/MM/yyyy")
public Date dueDate = new Date();
public static Finder<Long,Task> find = new Finder<Long,Task>(
Long.class, Task.class
);
}
実行時 に getter/setter を必要とするライブラリ (ORM、データバインダ、JSON バインダ、等) との互換性を保つため、Play はこれらを自動生成するように設計されてきました。 もしユーザが作成した getter/setter が Model で見つかった場合、Play は競合を避けるために getter/setter を生成しません。
警告:
(1) Ebean のクラス拡張はコンパイルの 後 に行われるので、**コンパイル時に Bbean が生成する getter/setter を利用できることを期待しないでください。** これらのメソッドを直接コーディングしたい場合は、getter/setter を自分で明示的に追加するか、例えばこれらを別のサブプロジェクトに配置するなどして、モデルクラスがプロジェクトの残りのクラスよりも前にコンパイルされることを保証してください。
(2) Ebean の (遅延評価を可能にする) フィールドに直接アクセスする拡張は、 Java クラスにのみ適用され、Scala には適用されません。このため、(Play の標準テンプレートを含む) Scala ソースファイルからのフィールド直接アクセスは遅延評価を実行せず、その結果、エンティティのフィールドは往々にして空 (未設定) になります。フィールドが設定されていることを保証するには、(a) getter/setter を手動で作成してフィールドアクセスの替わりに呼び出すか、(b) フィールドにアクセスする 前 にエンティティが完全に設定されていることを保証してください。
ご覧のように、 find
static フィールドが追加されました。これは識別子が Long
である Task
型のエンティティに対する Finder
を定義します。このヘルパーフィールドはモデルのクエリーを簡素化するために使われます。
// Find all tasks
List<Task> tasks = Task.find.all();
// Find a task by ID
Task anyTask = Task.find.byId(34L);
// Delete a task by ID
Task.find.ref(34L).delete();
// More complex task query
List<Task> tasks = find.where()
.ilike("name", "%coco%")
.orderBy("dueDate asc")
.findPagingList(25)
.setFetchAhead(false)
.getPage(1)
.getList();
§トランザクション管理されたアクション
Ebean はデフォルトでトランザクションを使用します。以下に示すように、このトランザクションはあらゆる クエリー、更新、作成または削除の前に作成され、これらの後にコミットまたはロールバックされます:
//Created implicit transaction
List<User> users =
Ebean.find(User.class)
.join("customer")
.where().eq("state", UserState.ACTIVE)
.findList();
//Transaction commited or rollbacked
//Created implicit transaction
Ebean.save(user);
//Transaction commited or rollbacked
そのため、同一のトランザクション中にふたつ以上のアクションを行いたい場合は、TxRunnable と TxCallable を使います:
// run in Transactional scope...
Ebean.execute(new TxRunnable() {
public void run() {
// code running in "REQUIRED" transactional scope
// ... as "REQUIRED" is the default TxType
System.out.println(Ebean.currentTransaction());
// find stuff...
User user = Ebean.find(User.class, 1);
...
// save and delete stuff...
Ebean.save(user);
Ebean.delete(order);
...
}
});
クラスが POJO の場合は、アクションメソッドに @play.db.ebean.Transactional
アノテーションを付けることで、メソッドにトランザクションを自動的に管理する Action
を組み合わせる事も出来ます。
@Transactional
public static Result save() {
...
}
あるいは古典的なアプローチを取りたい場合、明示的にトランザクションを開始、コミットそしてロールバックすることができます:
Ebean.beginTransaction();
try {
// fetch some stuff...
User u = Ebean.find(User.class, 1);
...
// save or delete stuff...
Ebean.save(u);
...
Ebean.commitTransaction();
} finally {
Ebean.endTransaction();
}
次ページ: JPA の統合
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。