停止Doctrine / Symfony在foreach期间加载相关实体? (懒惰加载没有发生)

时间:2014-08-26 00:42:01

标签: symfony doctrine-orm doctrine

我看到学说生成了额外的查询来加载我没有直接访问的实体。我认为延迟加载意味着这些关联实体不会被加载。你能帮我弄清楚查询发生的原因以及如何阻止它们吗?

以下是有问题的实体:

class Invoice
{
    /**
    * @ORM\OneToMany(targetEntity="InvoiceCard", mappedBy="invoice")
    */
    protected $cards;

    ...
}
class BaseInvoiceCard
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="Invoice", inversedBy="cards")
     * @ORM\JoinColumn(name="invoice_id", referencedColumnName="id")
     */
    protected $invoice;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="Printing")
     * @ORM\JoinColumn(name="printing_id", referencedColumnName="id")
     */
    protected $printing;

    ...
}
class InvoiceCard extends BaseInvoiceCard{ ... }
class Printing{ ... }

这行代码不会导致对InvoiceCards表的任何查询:

$cards = $invoice->getCards();

一旦我这样做了:

foreach($cards as $card){
    //do nothing in this loop
}

我得到一个" SELECT ... FROM invoicecard",这是预期的。

然而,我也得到了一个" SELECT ... FROM printing" $卡中的每张$卡。我从不打电话给$ card-> getPrinting()。即使我在循环中什么都不做,也会发生这种情况;只运行它会导致doctrine运行这些查询。

为什么会发生这种情况,我该如何预防?

编辑:这是getCards()的代码。

/**
 * Get cards
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getCards()
{
    return $this->cards;
}

编辑2: 我找到了解决这个问题的方法,但从长远来看,它不会解决问题。我将InvoiceCards作为一个数组取出,而不是让学说将它们作为实体加以水合。

$query->getArrayResult();

在我目前的情况下,这种技术无论如何都更好,因为我不需要完全补水的开销。

但是,该应用程序将在许多地方使用InvoiceCards,原始问题仍然是一个问题。我觉得要么我误解了Doctrine的延迟加载,要么它没有按预期工作。

1 个答案:

答案 0 :(得分:0)

实体正在急切地加载,因为Printing是一个父类,其子代使用单表继承。

如果我将$ printing更改为指向叶实体,则延迟加载将按预期工作。

来自Doctrine文档, 7.2.2. Performance impact

  

单表继承存在一般性能考虑:如果多对一或一对一关联的目标实体是STI实体,出于性能原因,它最好是叶子实体在继承层次结构中,(即没有子类)。否则,Doctrine 不能创建此实体的代理实例,并且始终急切地加载该实体。