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

  • 👏作者简介:大家好,我是冰点,从业11年,目前在物流独角兽企业从事技术方面工作,
  • 🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
  • 📝联系方式:iceicepip,加我进群,大家一起学习,一起进步👀

前言

在这里插入图片描述

有的时候我们需要对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;

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

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

  3. 在数据库中执行更新操作时,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中,这样它才能生效。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰点.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值