1、乐观锁的概念
乐观锁
:由名字就可以知道,它十分乐观,认为每次的更新修改
都不会被别人修改,所以不会上锁
操作,出现问题,、
再次判断新值测试
悲观锁
:名字就可以知道,它十分悲观,认为每次的更新修改
都会被别人修改,所以每次操作都会上锁
,再去操作
2、乐观锁实现方式
乐观锁实现的方式
:
取出记录时,获取当前version
更新时,带上这个version值
- 执行更新时,把
set version = newversion where version = oldversion
- 如果
version
不对,就更新失败
3、MybatisPlus实现乐观锁
1)在数据库表中增加字段version
,并设置默认值version=1
2)在javaBean实体类
中加上属性字段version
@Version
private Integer version;
@Version:乐观锁Version注解
3)注册组件
// 扫描mapper文件
@MapperScan("sz.kingdom.testmybatisplus.mapper")
@Configuration
public class MyConfiguration {
// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
4、测试
1)成功的测试案例
@Test
void TestOptimistSuccess() {
tb_user user1 = userMapper.selectById(7);
System.out.println("更新前:"+user1);
user1.setName("ted1");
int i = userMapper.updateById(user1);
System.out.println("更新后:"+user1);
}
输出日志:发现更新前后version值不一样
更新前:更新前:tb_user(userId=7, name=ted, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:46:31 CST 2021, version=6)
更新后:tb_user(userId=7, name=ted1, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:46:31 CST 2021, version=7)
JDBC Connection [HikariProxyConnection@2124562732 wrapping com.mysql.cj.jdbc.ConnectionImpl@1c93b51e] will not be managed by Spring
==> Preparing: SELECT user_id,create_time,psw,name,update_time,version FROM tb_user WHERE user_id=?
==> Parameters: 7(Integer)
<== Columns: user_id, create_time, psw, name, update_time, version
<== Row: 7, null, ycy0401, ted, 2021-11-22 12:46:31, 6
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6949e948]
更新前:tb_user(userId=7, name=ted, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:46:31 CST 2021, version=6)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67770b37] was not registered for synchronization because synchronization is not active
2021-11-22 20:46:48.943 INFO 18248 --- [ main] s.k.t.handler.MyMetaHanlder : 更新数据填充....
JDBC Connection [HikariProxyConnection@33389111 wrapping com.mysql.cj.jdbc.ConnectionImpl@1c93b51e] will not be managed by Spring
==> Preparing: UPDATE tb_user SET psw=?, name=?, update_time=?, version=? WHERE user_id=? AND version=?
==> Parameters: ycy0401(String), ted1(String), 2021-11-22 20:46:48.943(Timestamp), 7(Integer), 7(Long), 6(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67770b37]
更新后:tb_user(userId=7, name=ted1, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:46:31 CST 2021, version=7)
2)失败的测试案例(模拟多线程
)
@Test
void TestOptimistLock() {
tb_user user1 = userMapper.selectById(7);
System.out.println("更新前:"+user1);
user1.setName("xyc");
// 模拟多线程,线程1被打断,线程2获取执行权
tb_user user2 = userMapper.selectById(7);
user2.setName("sxf");
user2.setPsw("yps0401");
userMapper.updateById(user2);
System.out.println(user2);
// 线程1执行
System.out.println(user1);
userMapper.updateById(user1);
}
JDBC Connection [HikariProxyConnection@1182469998 wrapping com.mysql.cj.jdbc.ConnectionImpl@474179fa] will not be managed by Spring
==> Preparing: SELECT user_id,create_time,psw,name,update_time,version FROM tb_user WHERE user_id=?
==> Parameters: 7(Integer)
<== Columns: user_id, create_time, psw, name, update_time, version
<== Row: 7, null, ycy0401, ted1, 2021-11-22 12:47:57, 8
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66236a0a]
更新前:tb_user(userId=7, name=ted1, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:47:57 CST 2021, version=8)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67770b37] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@7508078 wrapping com.mysql.cj.jdbc.ConnectionImpl@474179fa] will not be managed by Spring
==> Preparing: SELECT user_id,create_time,psw,name,update_time,version FROM tb_user WHERE user_id=?
==> Parameters: 7(Integer)
<== Columns: user_id, create_time, psw, name, update_time, version
<== Row: 7, null, ycy0401, ted1, 2021-11-22 12:47:57, 8
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67770b37]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@73c31181] was not registered for synchronization because synchronization is not active
2021-11-22 20:48:46.472 INFO 21072 --- [ main] s.k.t.handler.MyMetaHanlder : 更新数据填充....
JDBC Connection [HikariProxyConnection@1710180594 wrapping com.mysql.cj.jdbc.ConnectionImpl@474179fa] will not be managed by Spring
==> Preparing: UPDATE tb_user SET psw=?, name=?, update_time=?, version=? WHERE user_id=? AND version=?
==> Parameters: yps0401(String), sxf(String), 2021-11-22 20:48:46.472(Timestamp), 9(Integer), 7(Long), 8(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@73c31181]
tb_user(userId=7, name=sxf, psw=yps0401, createTime=null, updateTime=Mon Nov 22 20:47:57 CST 2021, version=9)
tb_user(userId=7, name=xyc, psw=ycy0401, createTime=null, updateTime=Mon Nov 22 20:47:57 CST 2021, version=8)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@22bf9122] was not registered for synchronization because synchronization is not active
2021-11-22 20:48:46.485 INFO 21072 --- [ main] s.k.t.handler.MyMetaHanlder : 更新数据填充....
JDBC Connection [HikariProxyConnection@545392109 wrapping com.mysql.cj.jdbc.ConnectionImpl@474179fa] will not be managed by Spring
==> Preparing: UPDATE tb_user SET psw=?, name=?, update_time=?, version=? WHERE user_id=? AND version=?
==> Parameters: ycy0401(String), xyc(String), 2021-11-22 20:48:46.485(Timestamp), 9(Integer), 7(Long), 8(Integer)
<== Updates: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@22bf9122]
在模拟的线程1的更新没有成功