更新

DAOメソッドに @Update アノテーションを付けて更新を実行します。

@Dao
public interface EmployeeDao {
    @Update
    int update(Employee employee);

    @Update
    Result<ImmutableEmployee> update(ImmutableEmployee employee);
}

デフォルトでは、UPDATE ステートメントが自動生成されます。 @Update アノテーション内の sqlFile プロパティに true を指定することで、任意の SQL ファイルをマッピングできます。

パラメータが エンティティクラス であり、そのエンティティクラスにエンティティリスナーが指定されている場合、更新実行前にエンティティリスナーの preUpdate メソッドが呼び出されます。また、更新実行後はエンティティリスナーメソッドの postUpdate メソッドが呼び出されます。

戻り値

パラメータが不変のエンティティクラスの場合、戻り値はエンティティクラスを要素とする 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である

楽観的排他制御が有効な場合、バージョン番号がIDとともに更新条件に含まれ、バージョン番号は1 増分されて更新されます。更新件数が 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 が注釈されたプロパティがある場合、@Columnupdatable 要素が false のものは更新対象外です。

exclude

@Updateexclude 要素に指定されたプロパティを更新対象外とします。 プロパティがこの要素に指定されていれば、 @Columnupdatable 要素が true であっても更新対象外です。

@Update(exclude = {"name", "salary"})
int update(Employee employee);

include

@Updateinclude 要素に指定されたプロパティのみを更新対象とします。 @Updateinclude 要素と exclude 要素の両方に同じプロパティが指定された場合、そのプロパティは更新対象外になります。プロパティがこの要素に指定されていても、 @Columnupdatable 要素が false であれば更新対象外です。

@Update(include = {"name", "salary"})
int update(Employee employee);

excludeNull

@UpdateexcludeNull 要素が true の場合、値が null のプロパティを削除対象外とします。 この要素が true の場合、 @Columnupdatable 要素が true であったり、 @Updateinclude 要素にプロパティが指定されていても、値が null であれば更新対象外です。

@Update(excludeNull = true)
int update(Employee employee);

includeUnchanged

この要素は、更新対象のエンティティクラスに @OriginalStates が注釈されたプロパティがある場合にのみ有効です。

この要素がtrueの場合、エンティティの全プロパティが更新対象となります。 つまり、全プロパティに対応するカラムがUPDATE文のSET句に含まれます。

この要素が false の場合、エンティティが取得されてから実際に変更されたプロパティのみが更新対象になります。 つまり、変更されたプロパティに対応するカラムのみがUPDATE文のSET句に含まれます。

@Update(includeUnchanged = true)
int update(Employee employee);

SQLファイルによる更新

SQLファイルによる更新を行うには、 @UpdatesqlFile 要素に true を設定し、メソッドに対応するSQLファイルを用意します。

注釈

SQLファイルによる更新では 更新カラムリスト生成ディレクティブ を使用する場合と使用しない場合でルールが異なります。

更新カラムリスト生成ディレクティブを使用する場合

最初のパラメータの型はエンティティクラスである必要があります。指定できるパラメータの数に制限はありません。パラメータの型が基本型またはドメインクラスの場合、パラメータに 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による更新 と同様です。

更新カラムリスト生成ディレクティブを使用しない場合

パラメータとして任意の型を使用できます。指定できるパラメータの数に制限はありません。パラメータの型が基本型またはドメインクラスの場合、パラメータに 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ファイルにおけるバージョン番号と楽観的排他制御

以下の条件を満たした場合、楽観的排他制御が実行されます。

  • パラメータにエンティティクラスが含まれる

  • パラメータ内の左から最初のEntityクラスが @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

@UpdateignoreVersion 要素が true の場合、更新件数が0件であっても、 OptimisticLockException はスローされません。 また、エンティティのバージョンプロパティの値は変更されません。

@Update(sqlFile = true, ignoreVersion = true)
int update(Employee employee);
suppressOptimisticLockException

@UpdatesuppressOptimisticLockException 要素が true の場合、更新件数が0件であっても、 OptimisticLockException はスローされません。 ただし、エンティティのバージョンプロパティの値は1増分されます。

@Update(sqlFile = true, suppressOptimisticLockException = true)
int update(Employee employee);

一意制約違反

一意制約違反が発生した場合は、SQLファイルの使用の有無に関係なく UniqueConstraintException がスローされます。

クエリタイムアウト

結果セットのカラムにマッピングされないプロパティが存在する場合 ResultMappingException がスローされます。

@Update(queryTimeout = 10)
int update(Employee employee);

この指定はSQLファイルの使用の有無に関わらず適用されます。 queryTimeout プロパティの値が設定されていない場合は、 設定 で指定されたクエリタイムアウトが使用されます。

SQLログの出力形式

@UpdatesqlLog 要素に SQL のログ出力形式を指定できます。

@Update(sqlLog = SqlLogType.RAW)
int update(Employee employee);

SqlLogType.RAW はバインドパラメータ付きの SQL をログ出力することを表します。