我试图找出在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
直接在实体上
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;
}
}
我认为这是最糟糕的方式,因为它会获取所有相关交易以获取金额。
使用存储库
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。
使用服务模式
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上。
表非规范化,将余额保存到帐户表/实体中。
请让我知道你的建议。
答案 0 :(得分:6)
请记住,并非所有时间都可以拥有完全规范化的数据库。 在这种情况下,我建议进行非规范化,在您的帐户实体中保持余额。
然后,无论何时保存,只需记住所有新交易应与余额相加并在最后更新余额值。
通过这样做,您永远不需要生成SUM(),这对您的应用程序来说更好。