这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战
乐观锁
- 悲观锁:认为数据是不安全的,随时可能都有变动,无论什么时候都会加锁。再操作。
- 乐观锁:相对悲观锁而言,乐观锁任务数据是安全的,一般情况下不会出现问题,无论干什么都不去上锁。如果出现冲突,则返回错误信息,交给用户决定。
乐观锁实现方式
- 取出记录时,获取当前
version - 更新时,带上这个
version - 执行更新时,
set version = newVersion where version = oldVersion - 如果
version不对,就更新失败
使用乐观锁
- 数据库增加
version字段:
ALTER TABLE `table_name`
ADD COLUMN `version` INT DEFAULT 1 COMMENT '乐观锁';
- 给实体类增加字段
@Version
private Integer version;
- 注册乐观锁组件
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {
/**
* 用来配置mybatisPlus 插件
*
* @return 拦截器
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
- 测试成功
//测试乐观锁成功
@Test
public void testOptimisticLocker() {
//1.先获取用户信息
User user = userMapper.selectById(1L);
//2.修改用户信息
user.setName("test");
user.setAge(25);
//3.执行更新操作
userMapper.updateById(user);
}
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@74431b9c] was not registered for synchronization because synchronization is not active
2021-11-07 18:41:52.417 INFO 21884 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-11-07 18:41:52.792 INFO 21884 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1729992636 wrapping com.mysql.cj.jdbc.ConnectionImpl@774f2992] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, zbc, 14, test1@baomidou.com, null, 2021-11-06 22:28:53, 1
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@74431b9c]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@74ce7fdf] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@33779587 wrapping com.mysql.cj.jdbc.ConnectionImpl@774f2992] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: test(String), 25(Integer), test1@baomidou.com(String), 2021-11-07 18:41:52.93(Timestamp), 2(Integer), 1(Long), 1(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@74ce7fdf]
- 测试失败
//测试乐观锁失败
@Test
public void testOptimisticLocker2() {
//线程1
User user = userMapper.selectById(1L);
user.setName("test1");
//模拟线程2,先一步执行修改操作
User user2 = userMapper.selectById(1L);
user2.setName("test2");
userMapper.updateById(user2);
//如果没有乐观锁,就会覆盖线程2的值
userMapper.updateById(user);
}
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f2fb225] was not registered for synchronization because synchronization is not active
2021-11-07 18:46:35.982 INFO 13340 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-11-07 18:46:36.457 INFO 13340 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@2001676690 wrapping com.mysql.cj.jdbc.ConnectionImpl@602298b] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, test, 25, test1@baomidou.com, null, 2021-11-07 18:41:53, 2
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f2fb225]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@13908f9c] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@849031967 wrapping com.mysql.cj.jdbc.ConnectionImpl@602298b] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, test, 25, test1@baomidou.com, null, 2021-11-07 18:41:53, 2
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@13908f9c]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@642c72cf] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@966457052 wrapping com.mysql.cj.jdbc.ConnectionImpl@602298b] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: test2(String), 25(Integer), test1@baomidou.com(String), 2021-11-07 18:46:36.63(Timestamp), 3(Integer), 1(Long), 2(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@642c72cf]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6aa6c17] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1196877260 wrapping com.mysql.cj.jdbc.ConnectionImpl@602298b] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: test1(String), 25(Integer), test1@baomidou.com(String), 2021-11-07 18:46:36.68(Timestamp), 3(Integer), 1(Long), 2(Integer)
<== Updates: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6aa6c17]
我们发现后一条修改操作修改失败
| id | name | age | create_time | update_time | |
|---|---|---|---|---|---|
| 1 | test2 | 25 | test1@baomidou.com | null | 2021-11-07 18:46:37 |