Skip to content

Java客户端 乐观锁

He, Jiehui edited this page Dec 28, 2016 · 6 revisions

概述

Since:1.6.0

Version用于乐观锁更新。当更新操作执行的时候,version对应的字段会作为查询条件与主键一起包含在update语句里面。只有当version字段的值与数据库里面version值一致的情况下,更新才能成功

适用范围

适用于单表DAO里面的update和batchUpdate更新操作。

当前不支持携程的SqlServer,因为现在携程的SqlServer是通过SPA/SP3的方式来执行CUD操作。

使用说明

支持通过标注@Version作为表的版本字段。支持整形和时间戳类型。一个entity只能定义一个版本字段。

缺省版本递增

如果没有指定version字段不能更新,则在更新的时候DAL会自动更新版本。整形为加1操作,时间戳为获取数据库的时间戳 @Column(name="last_changed") @Type(value=Types.TIMESTAMP) @Version private Timestamp lastChanged;

数据库触发递增

如果数据库本身设置了更新的触发器能自动更新版本自动,则可以通过指定@Column里面的updatable=false来取消自动更新。 @Column(name="version", updatable=false) @Type(value=Types.INTEGER) @Version private Integer version;

版本值初始化

如果希望插入的时候也使用数据库的缺省值或触发器,可以通过指定@Column里面的insertable=false来在插入操作中去掉version字段。否则需要用户自己给版本赋值 @Column(name="last_changed", insertable=false) @Type(value=Types.INTEGER) @Version private Integer version;

例子

第一个是基于时间戳的,第二个是基于int的

注意:例子是直接调用的底层API,目的只是验证版本是否起效。实际运行时只用通过生成的dao里面的batchUpdate或update来完成即可 @Test public void testUpdatableWithVersion() throws SQLException { BatchUpdateTask test = new BatchUpdateTask<>(); DalParser parser = new DalDefaultJpaParser<>(UpdatableVersionModel.class, getDbName()); test.initialize(parser); DalTableDao dao = new DalTableDao(parser);

    DalHints hints = new DalHints();
     
    List<UpdatableVersionModel> pojos = dao.query("1=1", new StatementParameters(), new DalHints());
    long[] oldVer = new long[3];
    int i = 0;
    for(UpdatableVersionModel model: pojos){
        model.setAddress("1122334455");
        oldVer[i++] = model.getLastChanged().getTime();
    }
     
    int[] result = test.execute(hints, test.getPojosFieldsMap(pojos));
    assertArrayEquals(new int[]{1, 1, 1}, result);
    pojos = dao.query("1=1", new StatementParameters(), new DalHints());
    i = 0;
    for(UpdatableVersionModel model: pojos){
        assertEquals("1122334455", model.getAddress());
        Assert.assertTrue(oldVer[i++] <= model.getLastChanged().getTime());
    }
}
 
@Test
public void testUpdatableWithIntVersion() throws SQLException {
    BatchUpdateTask<UpdatableIntVersionModel> test = new BatchUpdateTask<>();
    DalParser<UpdatableIntVersionModel> parser = new DalDefaultJpaParser<>(UpdatableIntVersionModel.class, getDbName());
    test.initialize(parser);
    DalTableDao<UpdatableIntVersionModel> dao = new DalTableDao<>(parser);
     
    DalHints hints = new DalHints();
     
    Integer[] oldValue = new Integer[3];
    List<UpdatableIntVersionModel> pojos = dao.query("1=1", new StatementParameters(), new DalHints());
    int i = 0;
    for(UpdatableIntVersionModel model: pojos){
        model.setAddress("1122334455");
        oldValue[i++] = model.getTableIndex();
    }
     
    int[] result = test.execute(hints, test.getPojosFieldsMap(pojos));
    assertArrayEquals(new int[]{1, 1, 1}, result);
    pojos = dao.query("1=1", new StatementParameters(), new DalHints());
    i = 0;
    for(UpdatableIntVersionModel model: pojos) {
        assertEquals("1122334455", model.getAddress());
        Assert.assertTrue(oldValue[i++]+1 == model.getTableIndex());
    }
}