Collections 关于聚合域的一个域,如何使其保持最新?

Collections 关于聚合域的一个域,如何使其保持最新?,collections,doctrine-orm,associations,aggregate,Collections,Doctrine Orm,Associations,Aggregate,在doctrine2中,我有一个单一的关联:一个应用程序多个应用程序 在应用程序实体中,我有一个agregate字段sumCosts: /** * @ORM\Column(type="decimal", scale=2) */ protected $sumCosts; 在调用addCost和removeCost时更新: // Application.php public function addCost(ApplicationCost $cost) { if (!$this->

在doctrine2中,我有一个单一的关联:一个应用程序多个应用程序

在应用程序实体中,我有一个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);
    }
}
假设用户可以编辑现有的应用程序成本,并可以更改其父应用程序,如何确保此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;
}
那好吗?或者我在这里犯了一些巨大的错误,成本可能不同步

编辑:我读过条令的聚合字段烹饪书,我有版本控制(我使用锁定机制)。我的问题不是关于并发性


编辑:我创建了一些测试

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)之后至附录两项测试均为绿色。虽然我仍然怀疑我是否错过了什么。

好吧,我想我终于达到了预期的效果。我将对其进行描述,以供将来参考,以及任何可能有相同问题的人:

首先,批改课文

// 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}
选项(即在
costs
insideapplication.php上)。因此,无论何时添加/删除成本,它们都会被持久化

待续。。。(必须测试当我从拥有方更改应用程序并仅持久化ApplicationCost->旧应用程序和新应用程序都会更新吗?)

// 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);
}