检查和更新表中的记录时可能出现并发问题

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

情况就是这样,

会员必须兑换令牌才能访问(解锁)给定项目。相关的数据库表是:

表格1

Table MEMBER_BALANCE: MEMBER_ID, TOKEN_BALANCE

表2

Table UNLOCKED_ITEM: MEMBER_ID, DATE_UNLOCKED, ITEM_ID

我需要强制执行的检查或约束

  1. 当用户尝试解锁某个项目时,TOKEN_BALANCE必须> 0
  2. 用户之前没有解锁相同的项目。

我的直觉是在MemberService.java中编写一个简单的方法:

@Transactional
public void unlockItem(Member member, Item item){
    memberBalanceDAO.decrementBalance(member);
    itemDAO.unlockItem(member, item);
}

我已经通过在unique表上的MEMBER_ID / ITEM_ID对上添加UNLOCKED_ITEM约束来处理第二个要求。

我认为,我唯一需要注意的是,用户试图同时解锁许多物品,但TOKEN_BALANCE要求未得到满足。例如,TOKEN_BALANCE为1,但用户点击同时解锁两个项目。

下面是我的MemberBalanceDAO.decrementBalance方法:

@Transactional
public void decrementBalance(Member member) {
    MemberBalance memberBalance = this.findMemberBalance(member);
    if (memberBalance.getTokens() >= 1) {
        memberBalance.setTokens(memberBalance.getTokens() - 1);
        this.save(memberBalance);
    } else {
        throw new SomeCustomRTException("No balance");
    }
}

我不认为这可以保护我免受TOKEN_BALANCE = 1用例的影响。我担心同时有多个解锁请求。如果余额为1,我可以同时给decrementBalance()两次调用,同时将余额提交到0,然后同时也成功调用itemDAO.unlockItem(...),对吧?

我该如何实现呢?我应该将服务级别方法的事务设置为isolation = Isolation.SERIALIZABLE吗?或者有更清洁/更好的方法来解决这个问题吗?

java spring hibernate transactional optimistic-locking
1个回答
0
投票

我宁愿建议你在version表中介绍member_balance列。请参阅文档,Optimistic Locking

正如您所提到的,您无法修改架构;你可以使用无版本的乐观锁,explained here

或者你可能想要悲观锁定,explained here。然后,你可以修改你的方法,decrementBalance(),在那里获取成员余额,不要使用findMemberBalance()。例如,

@Transactional
public void decrementBalance(Member member) {
    MemberBalance memberBalance = entityManager.find(
        MemberBalance.class, member.id, LockModeType.PESSIMISTIC_WRITE,             
        Collections.singletonMap( "javax.persistence.lock.timeout", 200 ) //If not supported, the Hibernate dialect ignores this query hint.
    );
    if (memberBalance.getTokens() >= 1) {
        memberBalance.setTokens(memberBalance.getTokens() - 1);
        this.save(memberBalance);
    } else {
        throw new SomeCustomRTException("No balance");
    }
}

注意:它可能无法正常工作;它只是为你提供一些提示。

© www.soinside.com 2019 - 2024. All rights reserved.