同时更新实体依赖实体属性

时间:2012-05-25 15:33:10

标签: mysql jpa

我创建了一个实体User,它有整数属性事务配额。我需要根据其值更新事务配额。

如果大于0,则需要递减,否则需要保留其值。

所以这是我的算法。

  1. 从数据库中检索用户实体。
  2. 检查交易限额,如果交易额度大于0,则将其减少一个。
  3. 保留更改的用户实体。
  4. 在上面的情况下,当并发请求到来时,如果两个线程检索相同的用户实体和 然后两个线程读取相同的事务配额值,如果它大于0,则两者都减少1并更新用户实体。

    离。

    ThreadA: val = e.getTxnQuota(); val = 5
    ThreadB: val = e.getTxnQuota(); val = 5
    ThreadA: e.setTxnQuota(val- 1); val = 4 
    ThreadB: e.setTxnQuota(val- 1); val =4
    ThreadA: eDao.save(e);
    ThreadB: eDao.save(e);
    

    在上述情况下,保存的值为4而不是3.

    那么我有什么方法可以创建一个原子事务,我可以在其中检查事务配额并更新用户实体吗?

1 个答案:

答案 0 :(得分:1)

这称为锁定,通常更喜欢使用乐观锁定。 JPA有一个标准的机制来做到这一点。只需在您的实体中添加一个版本字段,然后使用@Version注释:

@Version
private long version;

Etvoilà!

每次保存用户时,其当前版本将与数据库中的版本进行比较,并递增:

update user set ..., version = version + 1 where id = ... and version = theVersionOfTheUserWhenItWasLoaded

(这一切都是透明的)。

如果版本不匹配,则不更新,JPA引擎检测到它,抛出OptimisticLockException,并标记事务以进行回滚。

附注:在上面的场景中,不需要调用save():对附加实体所做的所有更改都会自动保存在数据库中。无需保存实体。