保存

保存は、状態に応じて Bean を挿入または更新します。

Order order = new Order();
order.setOrderDate(new Date());
...
// insert the order
order.save();

Bean がフェッチされると更新されます...

Order order = DB.find(Order.class, 42);
order.setStatus(SHIPPED);
...
// update the order
order.save();

保存と削除は、関連する @OneToMany、@OneToOne などのアノテーションで指定された CascadeType に基づいてカスケードされます。

既定では、保存と削除はカスケードされません。そのため、save() または delete() がカスケードされるには、(以下の詳細にあるような) カスケードタイプを指定する必要があります。

...
@Entity
@Table(name="orders")
public class Order {

  ...
  @ManyToOne // no cascading
  Customer customer;

  @OneToMany(cascade=CascadeType.ALL) // save and delete cascaded
  List<OrderDetail> details;
	...

details プロパティの @OneToMany(cascade=CascadeType.ALL) に注意してください。これは、save() と delete() の両方が注文から注文の詳細にカスケードされることを意味します。

...
// save the order ...  will cascade also saving the order details
DB.save(order);

削除

削除は保存と非常によく似ています。DB.delete(); を呼び出すだけです。

...
Order order = DB.find(Order.class, 12);

// delete the order
// ... this will cascade also deleting the order details
// ... with either CascadeType.ALL or CascadeType.REMOVE
DB.delete(order);

カスケード

マッピングアノテーション @ManyToOne、@OneToMany、@OneToOne、@ManyToMany には、保存と削除がカスケードされるかどうかを制御するために使用されるカスケード属性があります。

既定では、保存または削除はカスケードされません (JPA 仕様による)。

次の例は、マッピングアノテーションを使用した Order エンティティ Bean を示しています。注文を保存すると、詳細も保存されますが、カスケード属性がなく、既定ではカスケードされないため、関連付けられた顧客は保存されません。

...
@Entity
@Table(name="orders")
public class Order {
  ...

  @ManyToOne // no cascading
  Customer customer;

  @OneToMany(cascade=CascadeType.ALL)  // save and delete cascaded
  List<OrderDetail> details;

バルク更新

更新は、挿入、更新または削除ステートメントを発行する方法を提供します。

これは、単一のステートメント (「バルク」更新と呼ばれることが多い) で複数の行 (または単一の行) を更新または削除する場合に役立ちます。

これは、最初にクエリを実行せずに更新または削除を実行する場合にも役立ちます。これは、ステートレス Web アプリケーションで更新を実行するための一般的なアプローチです。

このステートメントは、テーブル名と列名を使用した未加工の DML として、またはテーブル名の代わりにエンティティ名を使用し、列名の代わりにプロパティ名を使用する「論理的」な形式で提供できます。

// orm bulk delete use bean name and bean properties
DB.createUpdate(OrderDetail.class, "delete from orderDetail").execute();

// sql bulk update uses table and column names
DB.sqlUpdate("delete from country").execute();
`

バルク SQL 更新

類似した方法で SqlQuery では、名前付きパラメータまたは位置付きパラメータを使用した SQL INSERT、UPDATE または DELETE ステートメントを指定できます。

String dml = "update b_bug set title=:title where id = :id";
int rows = DB.sqlUpdate(dml)
  .setParameter("title", "Updated Again")
  .setParameter("id", 1)
  .execute();

CallableSql

CallableSql は、データベースストアドプロシージャを呼び出す方法を提供します。

String sql = "{call sp_order_mod(?,?)}";
CallableSql cs = DB.createCallableSql(sql);
cs.setParameter(1, "turbo");
cs.registerOut(2, Types.INTEGER);
DB.execute(cs);

// read the out parameter
Integer returnValue = (Integer) cs.getObject(2);

CallableSql を拡張することもでき、トランザクションから java.sql.Connection を取得して独自の JDBC API を使用してストアドプロシージャを呼び出すこともできます。

独自の JDBC

Ebean の機能ではアプリケーションの要件を満たせないことが予測できない場合もあります。必要な場合は、独自の JDBC を簡単に使用できることを知っておくとよいでしょう。

java.sql.Connection オブジェクトはトランザクションから返され、それで、希望するすべての独自の JDBC 呼び出しを実行できます。

これは、セーブポイント、高度な Clob/Blob の使用、または (CallableSql が目的に合ってはいない場合の) 高度なストアドプロシージャの呼び出しに役立ちます。

try (Transaction transaction = DB.beginTransaction()) {

  Connection connection = transaction.getConnection();
  // use raw JDBC
  ...

  transaction.commit();
}

JDBC バッチ

Ebean は、JDBC バッチ処理をサポートしています。バッチ処理は、関連する SQL ステートメントをバッチにグループ化し、1 回のデータベースへの呼び出しでそれらを送信します。

バッチ設定は application.properties または DatabaseConfig を通じて構成でき、トランザクションごとにオーバーライドできます。

保存されるエンティティのバッチモードは setBatch() で設定し、その子コレクションのバッチモードは setCascadeBatch() で設定できます。

...(工事中)... バッチモード、子バッチモード、バッチサイズを決定するためのより良いガイダンスを提供する必要があります

Transaction transaction = database.beginTransaction();
try {
  // turn of cascade persist
  transaction.setCascadePersist(false);

  // control the jdbc batch mode and size
  // transaction.setBatchMode(true); // equivalent to transaction.setBatch(PersistBatch.ALL);
  // transaction.setBatchMode(false); // equivalent to transaction.setBatch(PersistBatch.NONE);
  transaction.setBatch(PersistBatch.ALL); // PersistBatch: NONE, INSERT, ALL
  transaction.setCascadeBatch(PersistBatch.INSERT); // PersistBatch: NONE, INSERT, ALL
  transaction.setBatchSize(30);


  // for a large batch insert if you want to skip
  // getting the generated keys
  transaction.setGetGeneratedKeys(false);

  // for batch processing via raw SQL you can inform
  // Ebean what tables were modified so that it can
  // clear the appropriate L2 caches
  String tableName = "customer";
  boolean inserts = true;
  boolean upates = true;
  boolean deletes = false;
  transaction.addModification(tableName, inserts, updates, deletes);

  ...
} finally {
  transaction.end();
}
@Transactional を使用した例
@Transactional(batchSize = 50)
public void goodStuff() {

    order.save()
    customer.save()
}