ホーム > Java > MyBatis > 楽観的排他制御

楽観的排他制御

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);
        }
    }

リンク

コーポレートサイトにちょうどいいCMS、baserCMS