Mybatis-Plus 进阶开发-自定义乐观锁插件

简介: 有的时候我们需要对mybatis-plus的乐观锁插件进行自定义修改。那么其实mybatis 是已经有个默认的实现,我们只需要将其继承并扩展即可。0. OptimisticLockerInnerInterceptor 介绍当要更新一条记录的时候,希望这条记录没有被别人更新乐观锁实现方式:取出记录时,获取当前 version更新时,带上这个 version执行更新时, set version = newVersion where version = oldVersion如果 version 不对,就更新失败 但是我们也可以根据自己的业务需求实现自定义的乐观锁插件。Mybati

前言

b536c829abf6422b866fff5268226be0.png

有的时候我们需要对mybatis-plus的乐观锁插件进行自定义修改。那么其实mybatis 是已经有个默认的实现,我们只需要将其继承并扩展即可。

0. OptimisticLockerInnerInterceptor 介绍

当要更新一条记录的时候,希望这条记录没有被别人更新

乐观锁实现方式:


取出记录时,获取当前 version

更新时,带上这个 version

执行更新时, set version = newVersion where version = oldVersion

如果 version 不对,就更新失败 但是我们也可以根据自己的业务需求实现自定义的乐观锁插件。

Mybatis-Plus虽然已经提供了一个默认的乐观锁插件,但是我们也可以根据自己的业务需求实现自定义的乐观锁插件。

1. Mybatis-plus 实现乐观锁的原理

在MyBatis-Plus中,我们可以通过在实体类的版本号字段上添加@Version注解来标识乐观锁字段。在更新一条记录时,MyBatis-Plus会自动将版本号字段的值加1,然后将新的版本号值与更新语句一起发送到数据库中。如果更新成功,说明版本号没有冲突,否则会抛出乐观锁异常。

1. 在Mapper接口中定义更新方法

 int updateById(@Param(Constants.ENTITY) T entity);

2. 在实体类的版本号字段上添加@Version注解

public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    @Version
    private Integer version;
    // ...
}

在执行更新操作时,MyBatis-Plus会拦截更新语句,并根据实体类中的@Version注解来判断是否需要加入乐观锁机制。如果实体类中没有@Version注解,则不使用乐观锁机制。


如果实体类中有@Version注解,则MyBatis-Plus会自动将版本号字段的值加1,并将新的版本号值与更新语句一起发送到数据库中。


在数据库中执行更新操作时,MyBatis-Plus会根据更新语句中的版本号值来判断是否需要进行乐观锁校验。如果版本号值与数据库中的版本号值不一致,则说明版本号冲突,此时会抛出乐观锁异常。

2. 自定义乐观锁插件

1. 创建自定义乐观锁插件

先创建一个继承自Mybatis-Plus的OptimisticLockerInnerInterceptor的自定义乐观锁插件类,然后重写其beforeUpdate()方法来实现自己的乐观锁逻辑。

CustomOptimisticLockerInterceptor

public class CustomOptimisticLockerInterceptor extends OptimisticLockerInnerInterceptor {
    @Override
    public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) {
        // 获取实体类对象
        Object entity = getEntityFromParameter(parameter);
        // 获取乐观锁注解
        Version versionAnnotation = entity.getClass().getAnnotation(Version.class);
        if (versionAnnotation != null) {
            // 获取版本号字段名
            String versionColumn = versionAnnotation.value();
            // 获取版本号字段的值
            Object versionValue = getFieldValue(entity, versionColumn);
            // 如果版本号为空或者为0,则抛出乐观锁异常
            if (版本号为空或为0) {
                throw new OptimisticLockException("乐观锁异常:版本号为空或为0");
            }
            // 更新版本号字段值
            setFieldValue(entity, versionColumn, Integer.parseInt(versionValue.toString()) + 1);
        }
        // 调用父类的beforeUpdate()方法
        super.beforeUpdate(executor, ms, parameter);
    }
    private Object getEntityFromParameter(Object parameter) {
        if (parameter instanceof Map) {
            Map map = (Map) parameter;
            if (map.containsKey("et")) {
                return map.get("et");
            }
        } else if (parameter != null) {
            return parameter;
        }
        throw new MybatisPlusException("Failed to process, the parameter object is null.");
    }
    private Object getFieldValue(Object entity, String fieldName) {
        try {
            Field field = entity.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(entity);
        } catch (Exception e) {
            throw new MybatisPlusException("Failed to get field value.", e);
        }
    }
    private void setFieldValue(Object entity, String fieldName, Object value) {
        try {
            Field field = entity.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(entity, value);
        } catch (Exception e) {
            throw new MybatisPlusException("Failed to set字段值.", e);
        }
    }
}

2. 配置自定义乐观锁插件

在Mybatis-Plus的配置文件中,我们可以将自定义乐观锁插件配置为GlobalConfiguration的属性之一。下面是一个示例:

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new CustomOptimisticLockerInterceptor());
        return interceptor;
    }
}

在这个示例中,我们将自定义乐观锁插件添加到MybatisPlusInterceptor中,然后将其作为bean配置在MybatisPlusConfig类中。这样,我们就成功地配置了自定义乐观锁插件。

3. 总结

通过自定义乐观锁插件,我们可以根据自己的业务需求灵活地实现乐观锁机制。在实现自定义乐观锁插件时,我们需要重写OptimisticLockerInnerInterceptor的beforeUpdate()方法,并实现自己的乐观锁逻辑。最后,我们需要将自定义乐观锁插件配置到Mybatis-Plus的配置文件中。

在重写beforeUpdate()方法时,我们需要获取实体类对象、乐观锁注解、版本号字段名和版本号字段的值,并根据业务需求更新版本号字段的值。如果版本号为空或者为0,我们需要抛出乐观锁异常。

最后,我们需要将自定义乐观锁插件添加到MybatisPlusInterceptor中,这样它才能生效。

目录
相关文章
|
1月前
|
SQL Java 数据库连接
|
2月前
|
Java 数据库连接 Maven
使用mybatis插件generator生成实体类,dao层和mapper映射
使用mybatis插件generator生成实体类,dao层和mapper映射
48 0
|
16天前
|
SQL Java 数据库连接
【mybatis】第一篇,Springboot中使用插件PageHelper不生效解决方案
【mybatis】第一篇,Springboot中使用插件PageHelper不生效解决方案
|
3月前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
89 0
|
16天前
|
存储 关系型数据库 MySQL
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
|
16天前
|
Java 关系型数据库 MySQL
【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题
【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题
【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题
|
2月前
|
SQL XML Java
【JavaEE进阶】 MyBatis之动态SQL
【JavaEE进阶】 MyBatis之动态SQL
|
2月前
|
XML Java 数据库连接
【JavaEE进阶】 MyBatis使用XML实现增删改查
【JavaEE进阶】 MyBatis使用XML实现增删改查
|
2月前
|
Java 关系型数据库 数据库连接
【JavaEE进阶】 MyBatis使用注解实现增删改查
【JavaEE进阶】 MyBatis使用注解实现增删改查
|
2月前
|
Java 关系型数据库 数据库连接
【JavaEE进阶】MyBatis⼊⻔
【JavaEE进阶】MyBatis⼊⻔