バッチ更新
DAOメソッドに @BatchUpdate
というアノテーションを付けてバッチ更新を実行します。
@Dao
public interface EmployeeDao {
@BatchUpdate
int[] update(List<Employee> employees);
@BatchUpdate
BatchResult<ImmutableEmployee> update(List<ImmutableEmployee> employees);
}
デフォルトでは、UPDATE ステートメントが自動生成されます。 @BatchUpdate
アノテーション内の sqlFile
プロパティに true
を指定することで、任意の SQL ファイルをマッピングできます。
更新対象の エンティティクラス にエンティティリスナーが設定されている場合、エンティティリスナーの preUpdate
メソッドが更新実行前に各エンティティごとに呼び出されます。また、エンティティリスナーメソッドの postUpdate
メソッドは更新実行後に各エンティティごとに呼び出されます。
戻り値
パラメータ Iterable
のサブタイプの要素が不変エンティティクラスの場合、戻り値はエンティティクラスを要素として持つ org.seasar.doma.jdbc.BatchResult
でなければなりません。
上記の条件を満たさない場合、戻り値は各更新処理の更新件数を表す int[]
でなければなりません。
自動生成SQLによるバッチ更新
パラメータの型は要素として エンティティクラス を持つ java.lang.Iterable
のサブタイプでなければなりません。指定できるパラメータは 1 つだけです。パラメータは null
であってはなりません。戻り値の配列要素数は、 Iterable
の要素数と等しくなります。配列のそれぞれの要素が更新された件数を表します。
自動生成された SQL におけるバージョン番号と楽観的排他制御
以下の条件を満たした場合、楽観的排他制御が実行されます。
パラメータ java.lang.Iterable サブタイプ内の エンティティクラス に @Version アノテーションが付けられたプロパティがある
@BatchUpdate
アノテーション内のignoreVersion
要素がfalse
である
楽観的排他制御が有効であれば、バージョン番号はIDとともに更新条件に含まれ、 1増分して更新されます。 このときの更新件数が0件の場合、楽観的排他制御の失敗を示す BatchOptimisticLockException
がスローされます。 一方、更新件数が1件の場合は、 BatchOptimisticLockException
はスローされず、 エンティティのバージョンプロパティの値が1増分されます。
ignoreVersion
@BatchUpdate
の ignoreVersion
要素が true
の場合、 バージョン番号は更新条件には含まれず、UPDATE文のSET句に含まれます。 バージョン番号はアプリケーションで設定した値で更新されます。 この場合、更新件数が0件であっても、 BatchOptimisticLockException
はスローされません。
@BatchUpdate(ignoreVersion = true)
int[] update(List<Employee> employees);
suppressOptimisticLockException
@BatchUpdate
の suppressOptimisticLockException
要素が true
の場合、 @Version
が注釈されたプロパティがあればバージョン番号は更新条件に含まれ増分もされますが、 更新件数が0件であっても BatchOptimisticLockException
はスローされません。 ただし、エンティティのバージョンプロパティの値は1増分されます。
@BatchUpdate(suppressOptimisticLockException = true)
int[] update(List<Employee> employees);
更新対象プロパティ
更新可能
エンティティクラス に @Column
アノテーションが付けられたプロパティがある場合、 @Column
アノテーション内の false
が指定された updatable
プロパティは更新対象から除外されます。 。
exclude
@BatchUpdate
アノテーション内の exclude
プロパティで指定されたプロパティは更新対象から除外されます。 @Column
アノテーション内の updatable
プロパティに true が指定されていても、この要素でプロパティが指定されている場合、そのプロパティは更新対象から除外されます。
@BatchUpdate(exclude = {"name", "salary"})
int[] update(List<Employee> employees);
include
更新対象には @BatchUpdate
アノテーション内の include
プロパティで指定されたプロパティのみが更新対象となります。 @BatchUpdate 内の include プロパティと exclude プロパティの両方で同じプロパティを指定した場合、そのプロパティは更新対象から除外されます。この要素でプロパティを指定しても、 @Column アノテーション内の updatetable
プロパティが false
の場合、そのプロパティは更新対象から除外されます。
@BatchUpdate(include = {"name", "salary"})
int[] update(List<Employee> employees);
SQLファイルによるバッチ更新
SQLファイルによるバッチ更新を行うには、 @BatchUpdate
の sqlFile
要素に true
を設定し、 メソッドに対応するSQLファイルを用意します。
注釈
SQLファイルによるバッチ更新では、更新カラムリスト生成ディレクティブ を使用する場合と使用しない場合でルールが異なります。
更新カラムリスト生成ディレクティブを使用する場合
@BatchUpdate(sqlFile = true)
int[] update(List<Employee> employees);
@BatchUpdate
BatchResult<ImmutableEmployee> update(List<ImmutableEmployee> employees);
パラメータの型は要素として エンティティクラス を持つ java.lang.Iterable
のサブタイプでなければなりません。指定できるパラメータは 1 つだけです。パラメータは null
であってはなりません。戻り値の配列要素数は、 Iterable
の要素数と等しくなります。配列のそれぞれの要素が更新された件数を表します。
例えば、上記のメソッドに対応するには以下のようなSQLを記述します。
update employee set /*%populate*/ id = id where name = /* employees.name */'hoge'
パラメータ名は、SQL ファイル内の Iterable
の要素を示します。
更新対象プロパティの制御に関するルールは 自動生成SQLによるバッチ更新 と同等です。
更新カラムリスト生成ディレクティブを使用しない場合
@BatchUpdate(sqlFile = true)
int[] update(List<Employee> employees);
@BatchUpdate
BatchResult<ImmutableEmployee> update(List<ImmutableEmployee> employees);
パラメータの型は、任意の型を要素として持つ java.lang.Iterable
でなければなりません。指定できるパラメータは 1 つだけです。パラメータは null
であってはなりません。戻り値の配列要素数は、 Iterable
の要素数と等しくなります。配列のそれぞれの要素が更新された件数を表します。
例えば、上記のメソッドに対応するには以下のようなSQLを記述します。
update employee set name = /* employees.name */'hoge', salary = /* employees.salary */100
where id = /* employees.id */0
パラメータ名は、SQL ファイル内の Iterable
の要素を示します。
SQLファイルによるバッチ更新では、バージョン番号の自動更新は行われません。 また、 @BatchUpdate
の exclude
要素、 include
要素は参照されません。
SQLファイルにおけるバージョン番号と楽観的排他制御
以下の条件を満たした場合、楽観的排他制御が実行されます。
パラメータ内の java.lang.Iterable の要素は エンティティクラス であり、 @Version アノテーションが付けられたプロパティが エンティティクラス に存在する
@BatchUpdate アノテーション内のignoreVersion プロパティが false である
ただし、楽観的排他制御のSQLの記述はアプリケーション開発者の責任となります。たとえば、以下の SQL のように、WHERE 句でバージョン番号を指定し、SET 句でバージョン番号を 1 ずつインクリメントする必要があります。
update EMPLOYEE set DELETE_FLAG = 1, VERSION = /* employees.version */1 + 1
where ID = /* employees.id */1 and VERSION = /* employees.version */1
このSQLの更新件数が0件または複数件の場合、楽観的排他制御の失敗を示す BatchOptimisticLockException
がスローされます。 更新件数が1件の場合、 BatchOptimisticLockException
はスローされず、 エンティティのバージョンプロパティの値が1増分されます。
楽観的排他制御が有効であれば、バージョン番号は識別子とともに更新条件に含まれ、 1増分して更新されます。 このときの更新件数が0件または複数件の場合、楽観的排他制御の失敗を示す BatchOptimisticLockException
がスローされます。 一方、更新件数が1件の場合、 BatchOptimisticLockException
はスローされず、エンティティのバージョンプロパティの値が1増分されます。
ignoreVersion
@BatchUpdate
アノテーション内の ignoreVersion
プロパティが true
の場合、更新件数が何件であっても BatchOptimisticLockException
はスローされません。また、エンティティのバージョン プロパティは変更されません。
@BatchUpdate(sqlFile = true, ignoreVersion = true)
int[] update(List<Employee> employees);
suppressOptimisticLockException
@BatchUpdate
の suppressOptimisticLockException
要素が true
の場合、 更新件数が何件であっても BatchOptimisticLockException
はスローされません。 ただし、エンティティのバージョンプロパティの値は1増分されます。
@BatchUpdate(sqlFile = true, suppressOptimisticLockException = true)
int[] update(List<Employee> employees);
一意制約違反
一意制約違反が発生した場合は、SQLファイルの使用の有無に関係なく
UniqueConstraintException
がスローされます。
クエリタイムアウト
@BatchUpdate
アノテーション内の queryTimeout
プロパティにクエリタイムアウトの秒数を指定できます。
@BatchUpdate(queryTimeout = 10)
int[] update(List<Employee> employees);
この指定はSQLファイルの使用の有無に関わらず適用されます。 queryTimeout
プロパティに値が設定されていない場合は、config クラスで指定されたクエリタイムアウトが使用されます。
バッチサイズ
バッチサイズは @BatchUpdate
アノテーション内の batchSize
プロパティに指定できます。
@BatchUpdate(batchSize = 10)
int[] update(List<Employee> employees);
この指定はSQLファイルの使用有無に関わらず適用されます。 batchSize
プロパティに値を指定しない場合は、設定 クラスで指定されたバッチサイズが適用されます。
SQLログの出力形式
@BatchUpdate
アノテーション内の sqlLog プロパティに SQL ログの出力形式を指定できます。
@BatchUpdate(sqlLog = SqlLogType.RAW)
int[] update(List<Employee> employees);
SqlLogType.RAW
はバインドパラメータ(?)付きの SQL をログ出力することを表します。