-
Notifications
You must be signed in to change notification settings - Fork 447
Java客户端 乐观锁
He, Jiehui edited this page Jan 17, 2017
·
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来取消自动更新。
版本为1.6.0,1.6.1的updatable仅仅当Version存在的情况下才有效。1.6.2开始会单独使用.
@Column(name="version", updatable=false)
@Type(value=Types.INTEGER)
@Version
private Integer version;
如果希望插入的时候也使用数据库的缺省值或触发器,可以通过指定@Column里面的insertable=false来在插入操作中去掉version字段。否则需要用户自己给版本赋值
insertable可以单独使用
@Column(name="last_changed", insertable=false)
@Type(value=Types.INTEGER)
@Version
private Integer version;
第一个是基于时间戳的,第二个是基于int的
@Test
public void testUpdatableWithVersionByDao() throws SQLException {
DalParser<UpdatableVersionModel> parser = new DalDefaultJpaParser<>(UpdatableVersionModel.class, getDbName());
DalTableDao<UpdatableVersionModel> dao = new DalTableDao<UpdatableVersionModel>(parser);
DalHints hints = new DalHints();
List<UpdatableVersionModel> pojos = dao.query("1=1", new StatementParameters(), new DalHints());
for(UpdatableVersionModel model: pojos){
model.setAddress("1122334455");//Old value is SH INFO
Timestamp t = model.getLastChanged();
t.setTime(t.getTime()+100);
model.setLastChanged(t);
}
int[] result = dao.batchUpdate(hints, pojos);
assertArrayEquals(new int[]{0, 0 , 0}, result);
pojos = dao.query("1=1", new StatementParameters(), new DalHints());
for(UpdatableVersionModel model: pojos)
assertEquals("SH INFO", model.getAddress());//Still old value because version is incorrect
// Now the right case
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();
}
result = dao.batchUpdate(hints, 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 testUpdatableWithIntVersionByDao() throws SQLException {
DalParser<UpdatableIntVersionModel> parser = new DalDefaultJpaParser<>(UpdatableIntVersionModel.class, getDbName());
DalTableDao<UpdatableIntVersionModel> dao = new DalTableDao<>(parser);
DalHints hints = new DalHints();
List<UpdatableIntVersionModel> pojos = dao.query("1=1", new StatementParameters(), new DalHints());
int i = 0;
for(UpdatableIntVersionModel model: pojos){
model.setAddress("1122334455");
model.setTableIndex(-1);// Make the version incorrect
}
int[] result = dao.batchUpdate(hints, pojos);
assertArrayEquals(new int[]{0, 0, 0}, result);
pojos = dao.query("1=1", new StatementParameters(), new DalHints());
for(UpdatableIntVersionModel model: pojos)
assertEquals("SH INFO", model.getAddress());//Still old value because version is incorrect
// Now the right case
Integer[] oldValue = new Integer[3];
pojos = dao.query("1=1", new StatementParameters(), new DalHints());
i = 0;
for(UpdatableIntVersionModel model: pojos){
model.setAddress("1122334455");
oldValue[i++] = model.getTableIndex();
}
result = dao.batchUpdate(hints, 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());
}
}