赞
踩
转载自:www.javaman.cn
乐观锁和悲观锁是两种用于处理并发操作的数据锁定策略。它们在处理多个事务尝试同时访问和修改同一数据时的方法有所不同。
实战中使用:
SELECT ... FOR UPDATE
语句对选定的行或表加锁。在Java中,可以使用synchronized
关键字或ReentrantLock
等来实现悲观锁。OptimisticLockerInnerInterceptor
插件来简化乐观锁的使用。MyBatis-plus本身并不直接实现悲观锁或乐观锁,而是提供了与数据库的交互机制,使得开发者能够在应用中实现这两种锁策略。但是,为什么我们经常会看到 MyBatis 与乐观锁的结合,而与悲观锁的结合较少呢?这主要是因为两者在使用场景和适用性上的差异。
OptimisticLockerInnerInterceptor
插件可以简化这一过程,帮助开发者更容易地在应用中实现乐观锁。总结:MyBatis 本身并不防止悲观锁或乐观锁,而是提供了与数据库的交互机制。悲观锁主要依赖于数据库的功能来实现,而乐观锁则可以在应用层面得到 MyBatis-Plus 等工具的帮助。
MyBatis-Plus 提供了一个内置的乐观锁插件 OptimisticLockerInnerInterceptor
来帮助简化乐观锁的实现。以下是使用 MyBatis-Plus 实现乐观锁的基本步骤:
1.添加乐观锁插件:
在你的 MyBatis-Plus 配置中添加乐观锁插件。
@Configuration
@MapperScan({"com.ds.blog.system.mapper","com.ds.blog.admin.mapper"})
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//乐观锁插件
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
2.标记乐观锁字段:
在你的实体类中,使用 @Version
注解来标记作为乐观锁字段的属性,通常是版本号或时间戳。
public class Entity {
@Version
private Integer version;
// 其他字段和方法
}
OptimisticLockException
异常。OptimisticLockException
异常。通常的做法是重试更新操作或通知用户数据已被其他事务修改。注意:乐观锁策略的成功与否还取决于你的并发控制策略和业务场景。
具体步骤如下:
1.创建自定义拦截器类:
首先,你需要创建一个类来实现 MyBatis-Plus 的 InnerInterceptor
接口。这个接口定义了一些方法,允许你在 SQL 执行的不同阶段插入自定义逻辑。
import com.baomidou.mybatisplus.core.parser.SqlInfo;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class CustomOptimisticLockInterceptor implements InnerInterceptor {
// 你的自定义逻辑将在这里实现
}
2.实现拦截方法:
在你的自定义拦截器类中,你需要实现 processBefore
和 processAfter
方法。这些方法在 SQL 执行之前和之后被调用,允许你插入自定义逻辑。在这个例子中,我们关注 processBefore
方法,因为它允许我们在更新操作之前检查乐观锁。
@Override
public void processBefore(Executor executor, MappedStatement ms, Object parameter, String sql, SqlInfo sqlInfo) {
// 获取当前事务尝试更新的实体对象
Entity entity = (Entity) parameter;
// 获取原始版本号(通常从数据库中读取)
int originalVersion = entity.getVersion();
// 检查版本号是否已经被修改(意味着有其他事务已经更新了这条记录)
if (originalVersion != entity.getVersion()) {
throw new OptimisticLockException("数据已被其他事务修改");
}
// 如果需要检查其他字段或执行其他逻辑,可以在这里添加代码
}
3.注册自定义拦截器:
在你的 MyBatis-Plus 配置中,你需要注册你的自定义拦截器,以便它能够被正确地应用到你的 SQL 执行过程中。
@Configuration
@MapperScan({"com.ds.blog.system.mapper","com.ds.blog.admin.mapper"})
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new CustomOptimisticLockInterceptor());
return mybatisPlusInterceptor;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。