如何在DDD中调用复杂的SQL?

时间:2016-12-21 08:40:09

标签: repository domain-driven-design

我想以原子方式更新记录以保持一致性,可以使用以下SQL轻松完成。

UPDATE account SET balance = balance - 25 WHERE id = '5' AND balance > 25

或NoSQL(MongoDB)

db.account.update({_id: 5, balance: {$gte: 5}}, {$inc: {balance: -5}})

但在DDD中,如何在没有竞争条件的情况下正确地做到这一点?这应该很快,所以应该避免明确的锁定。 (除非DDD不可避免。)

可能会出现种族情况

class ApplicationService
  func creditAccount(String accountId, int amount)
    let account = accountRepository.find(accountId)
    account.credit(amount)
    accountRepository.save(account)

双重发送?

class ApplicationService
  func creditAccount(String accountId, int amount)
    let account = accountRepository.find(accountId)
    account.credit(amount, accountDao)

class Account
  func credit(int amount, AccountDao dao)
    this.balance = dao.adjustAmountAndReturn(this.id, -amount)

修改

我知道竞争条件的风险很低,但损失很大,因此成本乘以成本仍然会产生很高的预期值。

在这个问题中,我正在寻找一种适合RDBMS和NoSQL的解决方案。

1 个答案:

答案 0 :(得分:1)

我认为您可以使用该查询实现域服务,如:

interface CreditAccountService {
    void operation(String accountId, int amount);
}

class DbCreditAccountService implements CreditAccountService{
    void operation(String accountId, int amount){
        db.executeQuery("UPDATE account SET balance = balance - "+amount+" WHERE id = '"+accountId+"' AND balance > " + amount);
    }
}

但也许使用锁定机制更好地管理竞争条件 如果您的应用程序根本没有分配,那么使用实体ID进行悲观锁定就足以防止竞争条件......
如果您的应用程序被复制到' n'服务器并且具有一致的数据库,您可以在db表中使用乐观锁 或者也许是分布式锁定,如果您的数据库是分布式的并且最终是一致的。

您可以获得有关悲观/乐观锁定here

的更多信息