乐观锁
乐观锁(Optimistic Lock): 乐观锁是一种通过版本号(Version)或时间戳(Timestamp)来实现的并发控制机制。在更新数据时,会先检查数据版本号或时间戳是否匹配,如果匹配则更新数据并将版本号加一(或更新时间戳),否则认为是数据已经被其他事务修改过,不进行更新操作
乐观锁在Springboot中的实现
1.在数据库表中添加字段version
2.添加乐观锁配置
java
// 配置乐观锁
interceptor.addInnerInterceptor((new OptimisticLockerInnerInterceptor()));
return interceptor;
3.使用注解
java
public class Product {
private Long id;
private String name;
private Integer price;
@Version
private Integer version;
}
完整代码:
java
//实体
package com.qing.mybatislearning.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
import org.springframework.stereotype.Repository;
@Data
@TableName("t_product")
public class Product {
private Long id;
private String name;
private Integer price;
@Version
private Integer version;
}
//配置类
package com.qing.mybatislearning.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//扫描Mapper接口所在的包
@MapperScan("com.qing.mybatislearning.mapper")
public class MyBatisPlusConfig {
// Ctrl + p:查看方法的参数
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页配置
// 设置数据库类型为MYSQL,原因是不同数据库的分页方法不同
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 配置乐观锁
interceptor.addInnerInterceptor((new OptimisticLockerInnerInterceptor()));
return interceptor;
}
}
// 接口
package com.qing.mybatislearning.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qing.mybatislearning.pojo.Product;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}
//测试类
package com.qing.mybatislearning;
import com.qing.mybatislearning.mapper.ProductMapper;
import com.qing.mybatislearning.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MybatisPlusLeGuanSuoTest {
@Autowired
private ProductMapper productMapper;
@Test
public void Test1(){
//小李查询商品价格
Product productLi = productMapper.selectById(1);
System.out.println("小李获取的产品信息是: " + productLi.getPrice());
//小王查询商品价格
Product productWang = productMapper.selectById(1);
System.out.println("小王获取的产品信息是: " + productWang.getPrice());
//小李将价格+50
productLi.setPrice(productLi.getPrice() + 50);
productMapper.updateById(productLi);
//小王将价格-30
productWang.setPrice(productWang.getPrice() - 30);
int result = productMapper.updateById(productWang);
if(result == 0){
Product productWangNew = productMapper.selectById(1);
productWangNew.setPrice(productWangNew.getPrice() - 30);
productMapper.updateById(productWangNew);
}
//老板查询商品价格
Product productBoss = productMapper.selectById(1);
System.out.println("老板获取的产品信息是: " + productBoss.getPrice());
}
}
悲观锁
悲观锁(Pessimistic Lock): 悲观锁是一种在操作数据之前先加锁的机制,以避免数据被其他事务修改。在 MyBatis-Plus 中,可以通过 selectForUpdate
方法来实现悲观锁的功能,例如:
java
User user = userMapper.selectById(userId, new QueryWrapper<User>().forUpdate());
上面的代码会在查询用户数据时加上 for update
,使得查询结果被加上排它锁。
总的来说,乐观锁适合并发量不高的场景,通过版本号或时间戳来控制数据的更新;而悲观锁适合并发量高、需要确保数据一致性的场景,通过数据库锁来保证数据的完整性。在实际应用中,可以根据业务需求和系统的并发情况选择合适的锁机制。