Doctrine2加入SUM

时间:2012-03-27 16:52:17

标签: php design-patterns doctrine-orm

我试图找出在Doctrine 2中做到这一点的最佳方法。

我有一个账户实体,其中OneToMany为交易实体。我需要通过帐户过滤来自Transaction的所有值。在SQL中是这样的:SELECT a.*, SUM(t.amount) AS balance FROM account a INNER JOIN transaction t ON t.account_id = a.id

方法#1:

直接在实体上

class Account {
    // some other definitions

    /**
     * @OneToMany(targetEntity="Transaction", mappedBy="account")
     */
    private $transactions;

    public function getBalance() {
        $balance = 0;
        foreach ($this->transactions as $transaction){
            $balance += $transaction->getAmount();
        }
        return $balance;
    }
}

我认为这是最糟糕的方式,因为它会获取所有相关交易以获取金额。

方法#2:

使用存储库

class TransactionRepository {
    public function getBalanceByAccount(Account $account){
        $query = $this->em->createQuery("SELECT SUM(t.amount) FROM Transaction t INNER JOIN t.Account a WHERE a.id = ?");
        // ...
        return $query->getSingleScalarResult();
    }
}

我不确定它是否存在于TransactionRepository或AccountRepository。

方法#3:

使用服务模式

class TransactionService {
    public function getBalanceByAccountId($accountId){
        $query = $this->em->createQuery("SELECT SUM(t.amount) FROM Transaction t INNER JOIN t.Account a WHERE a.id = ?");
        // ...
        return $query->getSingleScalarResult();
    }
}

同样,我不确定它是否在TransactionService或AccountService上。

方法#4 :(由Guilherme Blanco

表非规范化,将余额保存到帐户表/实体中。

方法#n:

请让我知道你的建议。

1 个答案:

答案 0 :(得分:6)

请记住,并非所有时间都可以拥有完全规范化的数据库。 在这种情况下,我建议进行非规范化,在您的帐户实体中保持余额。

然后,无论何时保存,只需记住所有新交易应与余额相加并在最后更新余额值。

通过这样做,您永远不需要生成SUM(),这对您的应用程序来说更好。