更新
DAO メソッドに @Update を付けて、更新操作を実行します。
@Dao
public interface EmployeeDao {
@Update
int update(Employee employee);
@Update
Result<ImmutableEmployee> update(ImmutableEmployee employee);
}
デフォルトでは、UPDATE ステートメントが自動生成されます。 @Update アノテーション内の sqlFile プロパティに true を指定することで、任意の SQL ファイルをマッピングできます。
エンティティクラスパラメータにエンティティリスナーが指定されている場合、更新を実行する前にエンティティリスナーの preUpdate メソッドが呼び出されます。同様に、更新を実行した後、エンティティリスナーの postUpdate メソッドが呼び出されます。
戻り値
returning プロパティを使用する場合
returning
returning プロパティを使用しない場合
パラメータが不変エンティティクラスの場合、戻り値はそのエンティティクラスを要素とする org.seasar.doma.jdbc.Result でなければなりません。
上記の条件が満たされない場合、戻り値は更新された行数を表す int である必要があります。
自動生成されたSQLによる更新
パラメータの型はエンティティクラスである必要があります。指定できるパラメータは1つだけです。パラメータはnullであってはなりません。
@Update
int update(Employee employee);
@Update
Result<ImmutableEmployee> update(ImmutableEmployee employee);
自動生成された SQL におけるバージョン番号と楽観的排他制御
以下の条件を満たした場合、楽観的排他制御が実行されます。
パラメータのエンティティクラスが @Version アノテーションが付けられたプロパティを持つ
@Update アノテーション内のignoreVersion要素がfalseである
楽観的同時実行制御が有効になっている場合、バージョン番号は識別子とともに更新条件に含まれ、1ずつ増加されます。更新数が0の場合、楽観的同時実行制御の失敗を示すためにOptimisticLockException がスローされます。更新数が0でない場合、OptimisticLockException はスローされず、エンティティ内のバージョンプロパティは1増加します。
ignoreVersion
@Update アノテーション内の ignoreVersion プロパティが true の場合、バージョン番号は更新条件に含まれず、UPDATE ステートメント内の SET 句に含まれます。バージョン番号はアプリケーションで設定した値により更新されます。更新件数が 0 であっても OptimisticLockException はスローされません。
@Update(ignoreVersion = true)
int update(Employee employee);
suppressOptimisticLockException
@Update アノテーションの suppressOptimisticLockException プロパティが true の場合、@Version アノテーションが付けられたプロパティが存在すればバージョン番号は更新条件に含まれ増分もされますが、更新件数が0でも OptimisticLockException はスローされません。ただし、エンティティのバージョンプロパティの値は1増分されます。
@Update(suppressOptimisticLockException = true)
int update(Employee employee);
更新対象プロパティの制御
updatable
エンティティクラスのプロパティで @Column に注釈が付けられたもののうち、updatable プロパティが false に設定されているものは更新対象から除外されます。
exclude
@Update アノテーションの exclude プロパティに指定されたプロパティは更新対象から除外されます。たとえ @Column アノテーションの updatable プロパティが true に設定されていても、exclude プロパティにリストされているプロパティは更新されません。
@Update(exclude = {"name", "salary"})
int update(Employee employee);
include
@Update アノテーションの include プロパティに指定されたプロパティのみが更新されます。@Update の include プロパティと exclude プロパティの両方に同じプロパティがある場合、そのプロパティは更新されません。たとえ include プロパティにリストされていても、その @Column アノテーションの updatable プロパティが false に設定されている場合は更新されません。
@Update(include = {"name", "salary"})
int update(Employee employee);
excludeNull
@Update アノテーションのexcludeNull プロパティが true に設定されている場合、null の値を持つプロパティは更新されません。これは他の設定よりも優先されます - プロパティの@Column のupdatable 属性が true に設定されている場合や@Update アノテーションのincludeプロパティにそのプロパティがリストされている場合でも、その値がnull の場合は更新されません。
@Update(excludeNull = true)
int update(Employee employee);
includeUnchanged
このプロパティは、更新されるエンティティクラスに@OriginalStatesで注釈が付けられたプロパティが含まれている場合にのみ有効です。
この要素がtrueに設定されている場合、エンティティ内のすべてのプロパティが更新されます。つまり、すべてのプロパティに対応する列がUPDATEステートメントのSET句に含まれます。
この要素が false の場合、エンティティが取得されてから実際に変更されたプロパティのみが更新対象になります。つまり、変更されたプロパティに対応するカラムのみがUPDATE文のSET句に含まれます。
@Update(includeUnchanged = true)
int update(Employee employee);
returning
returning プロパティで @Returning を指定することで、SQL の UPDATE .. RETURNING 句に相当するコードを生成できます。
@Dao
public interface EmployeeDao {
@Update(returning = @Returning)
Employee update(Employee employee);
@Update(returning = @Returning(include = { "employeeId", "version" }))
Employee updateReturningIdAndVersion(Employee employee);
@Update(returning = @Returning(exclude = { "password" }))
Employee updateReturningExceptPassword(Employee employee);
@Update(returning = @Returning, suppressOptimisticLockException = true)
Optional<Employee> updateOrIgnore(Employee employee);
}
@Returning の include 要素を使用して、RETURNING 句によって返されるエンティティのプロパティ(データベース列に対応)を指定できます。また、exclude 要素を使用して、結果から除外すべきプロパティを指定することもできます。同じプロパティが include と exclude の両方に含まれている場合、それは返されません。
戻り値の型は、エンティティクラスまたはエンティティクラスを要素として含む Optional のいずれかでなければなりません。
注釈
この機能は、H2 Database、PostgreSQL、SQL Server、およびSQLiteのダイアレクトのみがサポートしています。
SQLファイルによる更新
SQLファイルによる更新を行うには、 @Update の sqlFile プロパティに true を設定し、メソッドに対応するSQLファイルを用意します。
注釈
SQLファイルによる更新では 更新カラムリスト生成ディレクティブ を使用する場合と使用しない場合でルールが異なります。
populate ディレクティブを使用する場合
最初のパラメータの型はエンティティクラスである必要があります。指定できるパラメータの数に制限はありません。パラメータの型が基本型またはドメインクラスの場合、パラメータに null を設定できます。型がそれ以外の場合、パラメータは null であってはなりません。
@Update(sqlFile = true)
int update(Employee employee, BigDecimal salary);
@Update(sqlFile = true)
Result<ImmutableEmployee> update(ImmutableEmployee employee, BigDecimal salary);
たとえば、上記のメソッドに対応するSQLは次のように記述します。
update employee set /*%populate*/ id = id where salary > /* salary */0
対象プロパティの更新制御に関するルールは 自動生成されたSQLによる更新と同様です。
populateディレクティブを使用しない場合
任意の型をパラメータとして使用できます。指定できるパラメータの数に制限はありません。パラメータの型が基本型またはドメインクラスの場合、パラメータに null を設定できます。型がそれ以外の場合、パラメータは null であってはなりません。
@Update(sqlFile = true)
int update(Employee employee);
@Update(sqlFile = true)
Result<ImmutableEmployee> update(ImmutableEmployee employee);
たとえば、上記のメソッドに対応するSQLは次のように記述します。
update employee set name = /* employee.name */'hoge', salary = /* employee.salary */100
where id = /* employee.id */0
@Update アノテーション内の exclude プロパティおよび include プロパティ、excludeNull プロパティ、includeUnchanged プロパティは、SQL ファイルによる更新時に参照されません。
SQLファイルにおけるバージョン番号と楽観的排他制御
以下の条件を満たした場合、楽観的排他制御が実行されます。
パラメータにエンティティクラスが含まれる
パラメータの 左端 のエンティティクラスは、@Version アノテーションが付けられたプロパティを持つ。
@Update アノテーション内のignoreVersion要素がfalseである
ただし、楽観的排他制御のSQLの記述はアプリケーション開発者の責任となります。たとえば、以下の SQL のように、WHERE 句でバージョン番号を指定し、SET 句でバージョン番号を 1 ずつインクリメントする必要があります。
update EMPLOYEE set DELETE_FLAG = 1, VERSION = /* employee.version */1 + 1
where ID = /* employee.id */1 and VERSION = /* employee.version */1
このSQL文の更新数が0の場合、楽観的排他制御の失敗を示す OptimisticLockException がスローされます。更新数が0でない場合、OptimisticLockException はスローされず、エンティティ内のバージョンプロパティは1増加されます。
ignoreVersion
@Update の ignoreVersion 要素が true の場合、更新件数が0件であっても、 OptimisticLockException はスローされません。 また、エンティティのバージョンプロパティの値は変更されません。
@Update(sqlFile = true, ignoreVersion = true)
int update(Employee employee);
suppressOptimisticLockException
@Update の suppressOptimisticLockException 要素が true の場合、更新件数が0件であっても、 OptimisticLockException はスローされません。 ただし、エンティティのバージョンプロパティの値は1増分されます。
@Update(sqlFile = true, suppressOptimisticLockException = true)
int update(Employee employee);
一意制約違反
SQLファイルの使用にかかわらず、ユニーク制約違反が発生すると UniqueConstraintException がスローされます。
クエリタイムアウト
@Update アノテーション内の queryTimeout プロパティにクエリタイムアウトの秒数を指定できます
@Update(queryTimeout = 10)
int update(Employee employee);
この仕様は、SQLファイルが使用されるかどうかにかかわらず適用されます。queryTimeout プロパティが設定されていない場合、設定 に指定されているクエリタイムアウトが適用されます。
SQLログの出力形式
@Update の sqlLog プロパティを使用して SQL ログ出力形式を指定できます。
@Update(sqlLog = SqlLogType.RAW)
int update(Employee employee);
SqlLogType.RAW は、バインドパラメータでSQLをログに記録することを示します。