我正在使用JPA(Hibernate)和Postgresql开发在Wildfly 8.1.0上运行的Java EE应用程序。我有传入的REST请求,这些请求可以并行地异步收入。
我有一个REST函数“递减”,除了其他东西之外,还会减少数据库中给定数量的值。所以这个功能需要 1)检索数据集(使用EntityManager) 2)从实体中读取值成员 3)减少该值 4)将其存储在实体中 5)保存此数据集(em.merge)
我需要一个锁定机制来锁定读取我的值,只要先前的读取值没有递减并存储回来(否则两个并行请求将读取相同的值,减少它并将其存储回来)
所以我在步骤1)和2)之间放置了em.lock(<entity>, LockModeType.PESSIMISTIC_WRITE)
。
然而,它似乎并没有解决我的矛盾问题。如果我运行一些并行测试循环,它请求我的减量方法(通过REST),我可以看到我没有那么多的减量,因为我有调用 - 即使使用em.lock。
好吧,如果我没有在<property name="javax.persistence.lock.timeout" value="1000"/>
中设置persistence.xml
,我会在开始第二个测试循环后得到很多LockTimeoutExceptions
,这表明已经设置了锁。
可能有什么不对? - 提前感谢您的帮助!
答案 0 :(得分:0)
使用乐观锁:
@Entity
public class MyEntity implements Serializable {
@Version
private long optimisticLockField; //will be under the management of the lock, do not modify
... other entity fields
}
答案 1 :(得分:0)
最后,我找到了一个解决这个问题的简单方法:我在查询中做了减量,例如。
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