Spring Boot,Spring Data JPA并发访问

7
我正在尝试使用Spring Boot和Spring Data JPA创建一个Restful API,以进行CRUD操作。数据库将是Oracle关系型数据库。现在对于并发访问,如果我们只使用@SpringTransactional进行spring事务处理,那么这样做是否足够满足我们的并发CRUD操作的目的呢?
我看到有JPA乐观锁定和悲观锁定策略版本列。我的具体问题是,对于并发CRUD操作,我们是否需要同时使用Spring事务和JPA锁定策略?或者只需相应地配置Spring事务即可满足要求?

1
这取决于您希望应用程序在并发CRUD操作存在的情况下如何运行。 - Jens Schauder
感谢@JensSchauder。我们想要的是多个用户可以进行并发CRUD操作。我们是否可以使用Spring事务或JPA乐观锁定来实现相同的功能。还是我们需要同时配置Spring事务和JPA锁定。 - adiCool
我已经理解了你的问题。但是,如果两个用户/进程同时尝试更改同一实体,你实际上想要发生什么?抛出异常?应用一个更改到另一个,覆盖第一个?阻止其中一个直到另一个完成?更不用说像如果有人在另一个人向相同实体添加“OrderItem”时编辑“Order”会发生什么这样的问题了。 - Jens Schauder
@JensSchauder 如果两个进程同时尝试更改同一实体,我希望其中一个被阻塞直到另一个完成。这是否只能通过Spring事务来实现? - adiCool
2个回答

12
尝试以下简单方法开始,在我看来,它在许多情况下都是合适的:使用乐观锁Spring Retry。 1)向您的实体中添加标记为@Versionversion属性(例如,您可以在基础抽象实体类中这样做,以简化该过程):
@Entity
public class MyEntity {

    @Id
    @GeneratedValue
    private Long id;

    @Version
    private Long version;

    // other stuff
}

在这种情况下,例如,当您更新实体时,Hibernate将使用version属性的当前值在更新查询的条件子句中,并将该值递增以将实体存储在其中。例如,下面是某些服务的代码:

@Transactional
public Optional<MyEntity> update(Long id, MyEntity source) {
    return myEntityRepository
           .findById(id)
           .map(target -> mapper.updateEntity(source, target));
}

将生成以下SQL查询:

1. select * from my_entities where id = ?; 
2. update my_entities set ..., version = <version value from query #1> + 1 where id = ? and version = <version value from query #1>;

如果另一个并发进程首先成功更新此实体,则您的方法将失败并引发异常(OptimisticLockException)。

2)为了管理该方法中的异常,请向其中添加@Retryable注释(并在配置或应用程序类上添加@EnableRetry注释):

@Retryable(maxAttempts = 2)
@Transactional
public Optional<MyEntity> update(Long id, MyEntity source) {
    // ...
}

在这种情况下,如果该方法出现异常,它将会在新的事务中再次被调用以重复操作。

额外信息:


1

乐观锁是JPA的默认策略。乐观锁适用于大多数应用程序。乐观锁更加简单高效。悲观锁需要在需要在提交事务之前知道冲突的情况下使用。

因此,您不需要配置锁定策略。


感谢@Ahmet Amasyali。这意味着只有正确配置Spring事务,才能帮助我们实现所需的并发行为,即并发CRUD操作。 - adiCool
1
@adiCool 是的。对于大多数情况,乐观锁应该足够了。 - Ahmet Amasyalı
但是我遇到了一些参考资料,它们说LockModeType.NONE是默认值。我猜当你使用EntityManager.find(Class, Object)时,默认的LockModeType会被使用。 - adiCool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接