mybatis 通过自定义 interceptor 实现乐观锁,核心是拦截 executor.update 方法,自动为带 @version 注解的实体字段添加 version = #{version} + 1 及 where version = #{version} 条件,并在 updatecount 为0时抛出 optimisticlockexception。

MyBatis 本身不内置乐观锁插件,但可通过 拦截器(Interceptor) 自定义实现乐观锁逻辑,核心是自动处理版本号字段(如 version)的读取、校验与自增。关键在于:查询时带出 version,更新时用 WHERE version = #{version} 条件,同时将 version +1 写回数据库。
配置乐观锁拦截器
编写一个实现 org.apache.ibatis.plugin.Interceptor 的类,拦截 Executor.update 方法,在 SQL 执行前动态改写 SQL 和参数:
- 识别带
@Version注解或约定命名(如字段名含version)的实体类 - 对
UPDATE语句,自动追加AND version = #{version}条件,并将version字段设为#{version} + 1 - 执行后检查
updateCount,若为 0 则抛出OptimisticLockException
实体类中声明版本字段
在 Java 实体类中标记版本字段,推荐使用注解统一识别:
- 添加自定义注解
@Version(如@Target(FIELD) @Retention(RUNTIME)) - 字段类型建议为
Integer或Long,初始值通常为0或1 - 示例:
public class User {<br> private Long id;<br> private String name;<br> @Version<br> private Integer version;<br> // getter/setter
Mapper XML 中配合写法
即使用了拦截器,XML 中仍需预留占位空间,确保 version 可被传入和更新:
-
UPDATE语句中显式设置version = #{version} + 1 -
WHERE子句必须包含AND version = #{version} - 避免全字段更新,防止覆盖 version 值;推荐用
<set></set>动态拼接非空字段
Spring Boot 中注册拦截器
通过 @Bean 方式注入自定义拦截器,确保其生效:
- 创建拦截器实例,设置属性如
versionFieldName(默认 "version") - 在
MybatisAutoConfiguration的SqlSessionFactory配置中加入interceptors - 注意拦截器顺序,避免与其他插件(如分页插件)冲突











