JPA利用@Version实现乐观锁的简单案例

1.乐观锁与悲观锁简介

  • 悲观锁:读锁可以共享,如果一个线程占用了写锁,则其他线程就不能获得写锁或读锁
  • 乐观锁:读锁可以共享,如果一个线程占用了写锁,其他线程仍可获得读锁或写锁,当该线程的事务进行提交的时候,会去判断是否有其他线程对该数据进行了修改(根据版本号或者其他方式),如果修改了,则不进行提交

2.JPA的实现方式简介(利用@Version注解)

2.1 创建实体类(数据库须增加version字段用来存储版本号)

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue( generator = "hibernate-uuid")
    @GenericGenerator( name = "hibernate-uuid",strategy = "uuid")
    @Column( name = "id")
    private String id;

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private Integer age;

    @Version
    @Column(name = "version")
    private Integer version = 0;
  
    get()/set()...
}

 

2.2编写业务代码

@Controller
@RequestMapping(value = "/a")
public class UserController {
    private static final Logger LOGGER = Logger.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @RequestMapping("/a")
    @ResponseBody
    public SimpleResult aaa() throws InterruptedException {

        SimpleResult result = new SimpleResult();
        User user = userService.findById("123");
        user.setName("张三");
        try {
            userService.saveOrUpdate(user);
        }catch (ObjectOptimisticLockingFailureException e){
            LOGGER.info(e);
            result.setResultCode("01");
            result.setResultMsg("已有其他用户对该条记录进行了修改");
            return result;
        }
        result.setResultCode("00");
        result.setResultMsg("修改成功");
        return result;
    }
}

 

2.3说明

如下图所示,有两个线程,线程A和线程B同时读到了下面这条数据,当线程A修改成功后,version自增1,而线程B再进行更新,此时version会自增1,然后去判断是否大于当前的version,结果1不大于1,抛出异常。

.

可以捕获该异常,并提示给用户,如下图所示。

3.乐观锁异常处理办法

上文采用捕获异常,并提示给用户的方式解决了抛出的异常,但有些场景不能用该方式来处理。比如支付场景,用户已经支付成功了,后台异步修改商户的余额,此时就不能因为乐观锁抛出的异常来告知用户支付失败。此时应能实现并发时也能修改余额。

3.1采用事务回滚重试来做乐观锁的重试机制,将这一部分的业务逻辑写在同一个事务中,发生异常,利用事务回滚,重新运行整个事务,直至成功为止,可参照  https://gist.github.com/crazycode/4970741或者可以尝试@Retry注解进行事务重试

3.2利用AOP来做乐观锁的重试机制   可参照https://nanjiwubing123.iteye.com/blog/2261394

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值