【发布时间】:2012-05-15 09:20:04
【问题描述】:
我有这笔交易:
em.getTransaction().begin();
{
final Payment payment = em.find(Payment.class, id);
if (payment.status != Status.INIT)
throw new IllegalStateException("Cannot set to PAID, is not INIT but " + status);
payment.status = Status.PAID;
}
em.getTransaction().commit();
log.info("Payment " + id + " was paid");
但是,正如您在此处看到的,事务不会阻止竞争条件:
[11:10:18.265] INFO [PaymentServlet] [MSP] Status COMPLETED
[11:10:18.265] INFO [PaymentServlet] Payment c76f9e75-99d7-4721-a8ac-e3a638dd8317 was paid
[11:10:18.267] INFO [PaymentServlet] [MSP] Status COMPLETED
[11:10:18.267] INFO [PaymentServlet] Payment c76f9e75-99d7-4721-a8ac-e3a638dd8317 was paid
两次付款设置为PAID。我的异常没有抛出,也没有回滚什么的。
我做错了什么?
【问题讨论】:
-
付款中有@Version 字段吗?
-
@Anonymoose 不,我在任何地方都没有特殊的并发性。我认为这就是交易的目的。
-
这是你的“特殊并发”。
-
@BartvanHeukelom 不,在这种情况下,事务并不意味着处理并发。为了防止并发编辑,您需要一些锁定机制,添加版本字段是一种方法(称为乐观锁定)。
标签: java hibernate jpa transactions race-condition