楽観的排他制御
versionカラムを使用して楽観的排他制御をおこなう。
1. Mapper
以下の様なMapperを用意する。
Mapperインターフェース例
public interface MakerQueryMapper {
int updateExclusive(@Param("maker") MakerMst maker);
}
xmlファイル例
<update id="updateExclusive" parameterType="com.ziqoo.demo.dao.table.model.MakerMst">
update maker_mst
<set>
<if test="maker.makerName != null">
maker_name = #{maker.makerName,jdbcType=VARCHAR},
</if>
<if test="maker.createAt != null">
create_at = #{maker.createAt,jdbcType=TIMESTAMP},
</if>
<if test="maker.updateAt != null">
update_at = #{maker.updateAt,jdbcType=TIMESTAMP},
</if>
version = #{maker.version,jdbcType=INTEGER} + 1
</set>
where id = #{maker.id,jdbcType=INTEGER}
and version = #{maker.version,jdbcType=INTEGER}
</update>
2. 動作確認と利用例
テストケース例
/**
* テストケース.
*/
@Test
@DatabaseSetup(type = DatabaseOperation.REFRESH, value = "/maker_query_mapper/setup")
void testUpdateExclusive() throws Exception{
MakerMst param = new MakerMst();
param.setId(8);
param.setMakerName("test");
param.setVersion(0);
updateExclusive(param);
// 同じversionで2度更新するとエラーが発生する.
ExclusiveException e = assertThrows(ExclusiveException.class, () -> updateExclusive(param));
assertEquals("既に更新されています。", e.getMessage());
}
/**
* 利用例.
*/
public void updateExclusive(MakerMst param) throws ExclusiveException {
int cnt = mapper.updateExclusive(param);
if (cnt == 0) {
throw new ExclusiveException("既に更新されています。");
}
}
/**
* 例外クラス例.
*/
public static class ExclusiveException extends Exception {
public ExclusiveException(String msg) {
super(msg);
}
}

