use*_*969 5 hibernate jpa optimistic-locking spring-data-jpa
我需要我的应用程序具有以下行为:
场景1
用户A查看订单。
用户B查看相同的订单。
场景2
使用 JPA(Hibernate via Spring Data JPA),我尝试用来@Version实现这种乐观锁定行为:
@Entity
public class Order {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
// many other fields
Run Code Online (Sandbox Code Playgroud)
删除时,UI 客户端向服务器提供订单 ID 列表以及每个订单 ID 的版本号。这篇文章(Spring Data JPA:删除乐观锁定语义)提到了一个标准解决方案:
if (entity.getVersion() != dto.getVersion()) {
throw new OptimisticLockException("...");
}
Run Code Online (Sandbox Code Playgroud)
要使用这个,我必须
问题是在步骤 2 中实体和 DTO 版本可能相同。但到了第3步,版本可能会有所不同。有没有办法让 hibernate 作为单个原子操作执行检查和更新,例如:
delete from [Order] where orderId = ? and version = ?
Run Code Online (Sandbox Code Playgroud)
StaleObjectStateException如果没有删除则抛出。
更新
我发现两种可行的方法。这两种方法之一有问题吗?第二种方法涉及较少的数据库访问。客户端通常一次仅发送一个要删除的订单,因此性能不应成为问题。
方法一
对于每个要删除的订单:
Order order = orderRepository.findById(
orderIdFromClient).orElseThrow(() ->
new OptimisticLockException());
if (!order.getVersion().equals(versionFromClient)) {
throw new OptimisticLockException();
}
// We now know the managed entity has the same version
// as the requested version. If some other transaction
// has changed the entity, Hibernate will rollback and
// throw OptimisticLockException.
orderRepository.delete(order);
Run Code Online (Sandbox Code Playgroud)
方法2
添加 OrderRepository 方法:
int deleteByIdAndVersion(Long id, Integer version);
对于每个要删除的订单:
int x = orderRepository.deleteByIdAndVersion(orderIdFromClient, versionFromClient);
if (x==0) {
throw new OptimisticLockException();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1299 次 |
| 最近记录: |