美文网首页
Java采坑之路-mybatis使用乐观锁

Java采坑之路-mybatis使用乐观锁

作者: 风一样的存在 | 来源:发表于2021-02-24 21:07 被阅读0次

由于公司的老项目使用的是struts2+mybatis+spring,有秒杀的场景,但是每次秒杀都有失败的情况。然后我这边引入了redisson分布式锁,但是还是没有控制住库存。查看了下日志发现原来分布式锁生效了,但是并发下每个线程读取的库存信息都是一样的,我开始怀疑是代码层面没啥问题,数据库事务没有提交,新的线程读取到了脏数据。
最后觉得应该在数据库层面进行控制,引入了乐观锁。为了不引入新的字段使用修改日期字段作为版本控制。

  • 第一步自定义注解
/**
 * 重试注解
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface IsTryAgain {
}
  • 第二步自定义切面
@Aspect
@Configuration
public class TryAgainAspect implements Ordered {

    /**
     * 默认重试几次
     */
    private static final int    DEFAULT_MAX_RETRIES = 3;

    private int                 maxRetries          = DEFAULT_MAX_RETRIES;
    private int                 order               = 1;

    public void setMaxRetries(int maxRetries) {
        this.maxRetries = maxRetries;
    }

    public int getOrder() {
        return this.order;
    }

    @Pointcut("@annotation(IsTryAgain)")
    public void retryOnOptFailure() {
        // pointcut mark
    }

    @Around("retryOnOptFailure()")
    @Transactional(rollbackFor = Exception.class)
    public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
        int numAttempts = 0;
        do {
            numAttempts++;
            try {
                //再次执行业务代码
                return pjp.proceed();
            } catch (TryAgainException ex) {
                if (numAttempts > maxRetries) {
                     //如果大于 默认的重试机制 次数,我们这回就真正的抛出去了
                    throw new ApiException(ApiResultEnum.ERROR_TRY_AGAIN_FAILED);
                }else{
                    //如果 没达到最大的重试次数,将再次执行
                    System.out.println("=====正在重试====="+numAttempts+"次");
                }
            }
        } while (numAttempts <= this.maxRetries);

        return null;
    }
}
  • 第三步在使用的地方添加注解

hibernatemybatis-plus都集成了乐观锁的实现。hibernate中使用version和timestamp标签支持版本控制,mybatis-plus中使用OptimisticLockerInterceptor插件。

相关文章

网友评论

      本文标题:Java采坑之路-mybatis使用乐观锁

      本文链接:https://www.haomeiwen.com/subject/ffylfltx.html