Jpa EntityManager:设置LockModeType.悲观_WRITE似乎不执行锁定

Jpa EntityManager:设置LockModeType.悲观_WRITE似乎不执行锁定,jpa,locking,java-ee-7,Jpa,Locking,Java Ee 7,我正在使用JPA(Hibernate)和Postgresql开发一个运行在Wildfly 8.1.0上的JavaEE应用程序。我有传入的REST请求,它可以以异步方式并行处理courese收入 我有一个REST函数“Decredit”,它将与其他函数一起,以给定的数量减少数据库中的值。所以这个函数需要 1) 检索数据集(使用EntityManager) 2) 从实体中读取值成员 3) 减小此值 4) 将其存储回实体中 5) 保存此数据集(em.merge) 我需要一个锁定机制来锁定读取我的值,只

我正在使用JPA(Hibernate)和Postgresql开发一个运行在Wildfly 8.1.0上的JavaEE应用程序。我有传入的REST请求,它可以以异步方式并行处理courese收入

我有一个REST函数“Decredit”,它将与其他函数一起,以给定的数量减少数据库中的值。所以这个函数需要 1) 检索数据集(使用EntityManager) 2) 从实体中读取值成员 3) 减小此值 4) 将其存储回实体中 5) 保存此数据集(em.merge)

我需要一个锁定机制来锁定读取我的值,只要前一个读取值未递减并存储回(否则两个并行请求将读取相同的值,递减并存储回) 因此,我将
em.lock(,LockModeType.悲观写入)
放在步骤1)和步骤2)之间

然而,它似乎并没有解决我的不一致性问题。如果我运行一些并行测试循环,它请求我的减量方法(超过REST),我可以看到我没有调用那么多的减量-即使使用em.lock

好吧,如果我没有在
persistence.xml
中设置
,那么在启动第二个测试循环后,我会得到很多
LockTimeoutExceptions
,这表明锁已经设置

有什么不对劲吗提前感谢您的帮助

使用乐观锁:

@Entity
public class MyEntity implements Serializable {
  @Version
  private long optimisticLockField; //will be under the management of the lock, do not modify

  ... other entity fields

}

最后,我为这个问题找到了一个简单的解决方案:我在查询本身中进行递减,例如

UPDATE Account a SET a.balance = a.balance - :value WHERE a = :account
当然,如果需要,我们也可以进行限额检查,例如,确保余额永远不会为负

UPDATE Account a SET a.balance = a.balance - :value WHERE a = :account AND a.balance >= :value

设置此锁后调用的SQL是什么?当使用相同的EntityManager时,我们将在下周一查看工作,并找出问题所在。但是,我认为这类锁是在JPA管理器(Hibernate)中管理的,不调用任何SQL。。。在数据存储中,我将尝试这样做。但是为什么另一种方法不起作用呢?我想这一定是有原因的,既然我还不是JPA的专家,我真的希望有人能给我指点。什么“其他方式”?JPA实现选择如何实现悲观TXN,正如我已经说过的,Hibernate最合乎逻辑的方法是将其添加到语句中(因此我要求发出SQL语句)。事实上,您可以在他们的手册中看到这一点,乐观锁定在这种情况下不是很好,因为更新冲突是预期的。所以我需要一个锁机制,就像悲观写一样,加上超时>0。如果我要使用乐观锁定,我需要处理异常,该异常会一直引发,然后?-我必须尝试重复“事务”(读取值、减量、存储)。