在doctrine2中,我有一个OneToMany关联:一个应用程序< =>许多ApplicationCost
// Application.php
/**
* @ORM\OneToMany(targetEntity="ApplicationCost", mappedBy="application", orphanRemoval=true)
*/
protected $costs;
// ApplicationCost.php
/**
* @ORM\ManyToOne(targetEntity="Application", inversedBy="costs")
* @ORM\JoinColumn(name="application_id", referencedColumnName="id")
*/
protected $application;
在应用程序实体中,我有一个agregate字段 sumCosts :
/**
* @ORM\Column(type="decimal", scale=2)
*/
protected $sumCosts;
调用addCost和removeCost时会更新:
// Application.php
public function addCost(ApplicationCost $cost)
{
if (!$this->costs->contains($cost)) {
$this->sumCosts += $cost->getBalance();
$this->costs[] = $cost;
$cost->setApplication($this);
}
return $this;
}
public function removeCost(ApplicationCost $cost)
{
if ($this->costs->contains($cost)) {
$this->sumCosts -= $cost->getBalance();
$this->costs->removeElement($cost);
}
}
假设用户可以编辑现有的ApplicationCost的并且可以更改它的父应用程序,我如何确保此agregate字段是最新的?
我的方法是:
// ApplicationCost.php
public function setApplication(Application $application = null)
{
if ($this->application !== null) {
$this->application->removeCost($this);
}
if ($application !== null) {
$application->addCost($this);
}
$this->application = $application;
return $this;
}
这样好吗?或者我在这里犯了一个很大的错误,sumCosts可能会不同步?
编辑:我读过Doctrine的Aggregate Fields食谱,我有版本控制(我使用锁定机制)。我的问题不是关于并发性。
编辑:我已经创建了一些测试
public function testSumCosts()
{
$app = new Application();
$costA = new ApplicationCost();
$costA->setBalance(150);
$costB = new ApplicationCost();
$costB->setBalance(100);
$costC = new ApplicationCost();
$costC->setBalance(50);
$app->addCost($costA);
$app->addCost($costB);
$app->addCost($costC);
$app->removeCost($costC);
$this->assertEquals(250, $app->sumCosts(), 'Costs are summed correctly');
}
public function testCostsChangeApplication()
{
$appA = new Application();
$appB = new Application();
$costA = new ApplicationCost();
$costA->setBalance(100);
$costB = new ApplicationCost();
$costB->setBalance(50);
$appA->addCost($costA);
$appB->addCost($costB);
$costA->setApplication($appB);
$costB->setApplication(null);
$this->assertEquals(0, $appA->sumCosts(), 'Costs are removed correctly');
$this->assertEquals(100, $appB->sumCosts(), 'Costs are added correctly');
}
将$cost->setApplication($this);
添加到 addEntry 后,两个测试均为绿色。虽然我仍然想知道我是否可能错过了什么。
答案 0 :(得分:0)
好吧,我想我终于取得了理想的结果。我将描述它以供将来参考,以及任何可能遇到同样问题的人:
首先纠正班级
// Application.php
public function addCost(ApplicationCost $cost)
{
if (!$this->costs->contains($cost)) {
$this->sumCosts += $cost->getBalance();
}
$this->costs[] = $cost;
return $this;
}
public function removeCost(ApplicationCost $cost)
{
if ($this->costs->contains($cost)) {
$this->sumCosts -= $cost->getBalance();
}
$this->costs->removeElement($cost);
}
如果将其与原始代码进行比较,您会发现只有更新agregate字段才有条件。它没有坏处,因为集合不能容纳重复的元素,也不能删除不存在的元素。
其次,在关联的反面配置cascade={all}
选项(即在 Application.php 内的costs
上)。因此,无论何时添加/删除成本,它们都会被保留。
继续...... (必须测试当我从拥有方改变应用程序时会发生什么,并且只保留ApplicationCost - >新旧应用程序是否会更新?)