3.4、乐观锁插件
3.4.1、主要适用场景
意图:
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
3.4.2、插件配置
spring xml:
代码语言:javascript复制<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
spring boot:
代码语言:javascript复制@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
3.4.3、注解实体字段
需要为实体字段添加@Version注解。
第一步,为表添加version字段,并且设置初始值为1:
代码语言:javascript复制ALTER TABLE `tb_user`
ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE `tb_user` SET `version`='1';
第二步,为User实体对象添加version字段,并且添加@Version注解:
代码语言:javascript复制@Version
private Integer version;
3.4.4、测试
测试用例:
代码语言:javascript复制@Test
public void testUpdate(){
User user = new User();
user.setAge(30);
user.setId(2L);
user.setVersion(1); //获取到version为1
int result = this.userMapper.updateById(user);
System.out.println("result = " result);
}
执行日志:
代码语言:javascript复制main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]-[DEBUG]
Original SQL: UPDATE tb_user SET age=?,
version=? WHERE id=? AND version=?
[main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]-[DEBUG]
parser sql: UPDATE tb_user SET age = ?, version = ? WHERE id = ? AND version = ?
[main] [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching JDBC
Connection from DataSource
[main] [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC
Connection [HikariProxyConnection@540206885 wrapping
com.mysql.jdbc.JDBC4Connection@27e0f2f5] will not be managed by Spring
[main] [cn.itcast.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Preparing: UPDATE
tb_user SET age=?, version=? WHERE id=? AND version=?
[main] [cn.itcast.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Parameters:
30(Integer), 2(Integer), 2(Long), 1(Integer)
[main] [cn.itcast.mp.mapper.UserMapper.updateById]-[DEBUG] <== Updates: 1
[main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30135202]
result = 1
可以看到,更新的条件中有version条件,并且更新的version为2。
如果再次执行,更新则不成功。这样就避免了多人同时更新时导致数据的不一致。
3.4.5、特别说明
支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion 1
newVersion 会回写到 entity 中仅支持 updateById(id) 与 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!