狂神说Java:https://www.bilibili.com/video/BV17E411N7KN?p=8学习笔记
一、更新数据
@Test
public void updateTest(){
User user = new User();
user.setId(1L);
user.setName("README");
user.setAge(18);
user.setEmail("[email protected]");
//由源码知:虽然方法名叫updateById,但参数是对象
int result = userMapper.updateById(user);
System.out.println(result);
}
二、自动填充
创建时间,修改时间这些操作一般都是自动完成的(不希望手动更新)。自动更新有两种方式
方式一:在数据库中配置(工作中不建议使用)
方式二:
- 在实体类中字段属性上添加注解
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
- 编写处理器处理此注解
@Slf4j
@Component //要把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
三、乐观锁
- 乐观锁:总是认为不会出现问题,无论干什么都不去上锁。如果出现了问题,再次更新值测试
- 悲观锁:总是认为会出现问题,无论干什么都会上锁,再去操作
实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
--A
update user set name = "README",version = version + 1
where id = 2 and version = 1
--B 线程抢先完成,这时候version = 2,会导致A修改失败!
update user set name = "README",version = version + 1
where id = 2 and version = 1
1.给数据库中加version字段
2.在实体类中添加对应字段及乐观锁注解@version
//乐观锁version注解
@Version
private Integer version;
3.注册组件
@MapperScan("com.zhou.mapper")
@EnableTransactionManagement
@Configuration //代表这是配置类
public class MyBatisPlusConfig {
//注册乐观锁
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
4.测试
//单线程测试成功
@Test
public void testOptimisticLocker(){
//查询用户信息
User user = userMapper.selectById(1L);
//修改用户信息
user.setName("Morning");
user.setEmail("[email protected]");
//执行更新操作
userMapper.updateById(user);
}
//多线程测试失败
@Test
public void testOptimisticLocker(){
User user = userMapper.selectById(1L);
user.setName("Morning");
user.setEmail("[email protected]");
//user2插队操作
User user2 = userMapper.selectById(1L);
user2.setName("night");
user2.setEmail("[email protected]");
userMapper.updateById(user2);
//如果没有乐观锁,它会覆盖插队线程的值
//可以用自旋锁来尝试多次提交
userMapper.updateById(user);
}