Documentation

You are viewing the documentation for the 2.2.0 release in the 2.2.x series of releases. The latest stable release series is 2.4.x.

§Ebean ORM を使う

§Ebean の設定

Play には Ebean ORM が同梱されています。有効にするには、依存性に javaEbean を追加します :

val appDependencies = Seq(
  javaEbean
)

その後、以下の行を conf/application.conf に追加します。

ebean.default="models.*"

ここでは default データソースを使用する default Ebean サーバを定義していて、これは適切に設定する必要があります。 Ebean サーバは必要な分だけ作ることができ、また各サーバにマップされるクラスを明確に定義する事も出来ます。

ebean.orders="models.Order,models.OrderItem"
ebean.customers="models.Customer,models.Address"

この例では、2 つの Ebean サーバへのアクセスが設定されています。各サーバはそれぞれ異なるデータベースを使用しています。

(上記した) それぞれの ebean. 設定行は、Ebean が登録することに関心を持つ あらゆる クラス (例えば @Entity/Model クラス, @Embeddable, カスタマイズした ScalarTypeCompoundType, 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);

§トランザクション管理されたアクション

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 の統合