首页 > 解决方案 > Spring JPA,结合@Lock 和@Transactional 来同步并发数据库访问

问题描述

我正在实现一个工作流,其中一个实体可以由于两个并发事件而被更新:

public void onSomethingHappened(int entityId)
    entity = repository.findById(entityId)
    if (entity == null) {
        entity = createNew()
    }
    entity.doSomething()
    repository.save(entity)

public void onSomethingElseHappened(int entityId)
    entity = repository.findById(entityId)
    if (entity == null) {
        entity = createNew()
    }
    entity.doSomethingElse()
    repository.save(entity)

所以我想要防止这种情况发生,例如,onSomethingHappened在另一个方法正在执行时正好读取数据库,因为这将导致在onSomethingElseHappened执行相同操作时创建实体的实例,从而产生脏读

我想到的第一件事是用悲观锁定来处理这种情况,并使这两种方法都 @Transactional 并设置 @Lock on repository.findById()。我的期望是两个事务中的一个将获取锁并在方法执行结束时释放它,所以另一个方法在另一个方法保存实体之前不会完成读取,这样读取就会产生非空结果

但是,文档似乎没有提供有关它的更多信息

另一种选择可能是使用乐观并发控制,在 Entity 中使用 @Version 注释字段并在它们引发OptimisticLockException...but时重试这两个操作之一

那么,悲观锁定方式可行吗?如果不是,如何确保乐观锁定在插入行的情况下有效?

标签: javaspringhibernatejpaconcurrency

解决方案


推荐阅读