目录
乐观锁和悲观锁
乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不去上锁,如果出现了问题,在次更新值测试
在数据库中新增字段version,在实体类中也要增加对应的,使用@Version表示他是一个乐观锁
乐观锁:先查询,获取它的版本号,然后在一系列的操作后,让他的版本号+1,前提是这个版本号还是之前查出来的那个版本号。
@Version//乐观锁
private Integer version;
写一个配置类
@Configuration
@MapperScan("com.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
测试乐观锁单线程成功的例子
更新下
@Test
void update() {
User user = userMapper.selectById(5L);
user.setName("kongchaoAfter");
user.setAge(21);
user.setEmail("[email protected]");
userMapper.updateById(user);
}
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中- 仅支持
updateById(id)
与update(entity, wrapper)
方法 - 在
update(entity, wrapper)
方法下,wrapper
不能复用!!!
乐观锁多线程失败案例
@Test
void update2() {
//线程1
User user = userMapper.selectById(5L);
user.setName("kongchao1");
user.setAge(11);
user.setEmail("[email protected]");
//模拟另一个线程插队
User user2 = userMapper.selectById(5L);
user2.setName("kongchao2");
user2.setAge(22);
user2.setEmail("[email protected]");
userMapper.updateById(user2);
//若没有乐观锁,则会覆盖user2的操作
userMapper.updateById(user);
}
数据库
运行结果
查询操作
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
// 测试批量查询!
@Test
public void testSelectByBatchId(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
@SpringBootTest
@MapperScan("com.mapper")//扫描mapper,自动创建实现类
class MybatisPlusQuickApplicationTests {
@Autowired
private UserMapper userMapper;
//按条件查询之一使用map操作
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> map = new HashMap<>();
// 自定义要查询
map.put("name","kc");
map.put("age",18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
}
分页查询
在配置类中加入分页插件
@Configuration
@MapperScan("com.mapper")
public class MyBatisPlusConfig {
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
在测试类中测试
//测试分页查询
@Test
public void pageTest(){
//第一页,每页三个数据
Page<User> page=new Page<>(1, 3);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::print);
}
可以获取各种参数
运行结果
删除操作
删除单个
@Test
public void deleteById(){
userMapper.deleteById(1583366844257988614L);
}
删除多个
//删除多个
@Test
public void deleteByIds(){
userMapper.deleteBatchIds(Arrays.asList(1583366844257988612L,1583366844257988613L));
}
按map删除
//通过map删除
@Test
public void deleteMap(){
HashMap<String,Object> hashMap=new HashMap<>();
hashMap.put("name", "kc");
userMapper.deleteByMap(hashMap);
}
逻辑删除
物理删除:从数据库中移除
逻辑删除:数据还存在数据库中,是增加了一个deleted字段,以这个字段作为条件,当字段=1时不显示这条数据
这个功能类似于回收站。并没有真正删除。
在数据库中添加字段deleted然后在实体类中也加入,并带上注解
@TableLogic//逻辑删除
private Integer deleted;
在application.yaml配置文件中配置
mybatis-plus:
global-config:
db-config:
# 没有逻辑删除的显示为0,否则显示1
logic-delete-value: 1
logic-not-delete-value: 0
测试之前的删除
//逻辑删除单个
@Test
public void deleteById(){
userMapper.deleteById(6L);
}
运行结果,删除只是将deleted字段变为1
测试查询
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(6L);
}
运行结果,发现也会加上deleted=0的条件