异步更新实体列表并检测最后一项何时被处理

问题描述 投票:0回答:1

我有一个 Order 类,其中包含订单行列表:

public class Order {

  @Id
  @GeneratedValue(strategy = GenerationType.UUID)
  private UUID uuid;

  @Enumerated(EnumType.STRING)
  private OrderStatus status;

  @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL,
      orphanRemoval = true)
  private List<OrderLine> orderLines;
}

还有

public class OrderLine {

  @Id
  @GeneratedValue(strategy = GenerationType.UUID)
  private UUID uuid;

  @ManyToOne
  @JoinColumn(name = "order_uuid", referencedColumnName = "uuid")
  private Order order;

  @Enumerated(EnumType.STRING)
  private OrderLineStatus status;
}

当我验证订单时,我会为他的每行发送一个事件,因此每行都会单独验证。其他应用程序处理这些事件并发回每行的验证事件。当我的应用程序捕获这些验证事件时,它会更新线路状态,然后检查它是否是最后一个要处理的线路。如果它是最后一个要处理的订单,则会更新订单状态。

到目前为止我已经做到了:

  public void handleEvent(Event event) {
    OrderLine orderLine = orderLineService.findById(event.getOrderLineUuid());
    if (!OrderLineStatus.VALIDATED.equals(orderLine.getStatus())
        && !OrderStatus.VALIDATED.equals(orderLine.getOrder().getStatus())) {
      // Update using @Modifying
      orderLineService.updateStatusAndError(
          OrderLineStatus.VALIDATED, null, orderLine.getUuid());
      checkIfLastOrderLine(orderLine.getOrder());
  }

  public void checkIfLastOrderLine(final Order order) {
    // A pessimistic read lock is set on countByStatusAndOrderUuid 
    long stillProcessingCounter = orderLineService
        .countByStatusAndOrderUuid(OrderLineStatus.PENDING_FOR_VALIDATION, order.getUuid());
    if (stillProcessingCounter == 0) { // All lines processed
      // Update order status
      // Do other stuff that need to be done only once
    }
  }

但是当我测试它时,我的订单状态会更新多次。我还尝试在 checkIfLastOrderLine 上进行同步,但我们有多服务器服务,因此任何服务器都可以处理任何事件。

我正在考虑在我的订单上实施一个计数器来跟踪经过验证的订单行,但我不知道这是否是一个好主意。

感谢您的帮助!

spring-boot hibernate jpa asynchronous
1个回答
0
投票

我会尝试在

OrderStatus
字段上同步。

在订单存储库中添加将更新订单状态的方法(如果当前状态为

PENDING_FOR_VALIDATION
(或您使用的任何枚举值))。此方法返回许多修改的行。

@Query("update order set order_status = ? where orderId = ? and order_status = 'PENDING_FOR_VALIDATION'", nativeQuery = true)
@Modifying
int updateOrderStatus(OrderStatus orderStatus, UUID orderId);

这意味着,

updateOrderStatus
应该仅针对单个事件处理程序返回
1
。 我相信它应该与
stillProcessingCounter
一起使用,如下

if (stillProcessingCounter == 0 and updateOrderStatus(VALID, order.getUUID() == 1) {
// do some logic that should be executed only once
}
© www.soinside.com 2019 - 2024. All rights reserved.