我看到学说生成了额外的查询来加载我没有直接访问的实体。我认为延迟加载意味着这些关联实体不会被加载。你能帮我弄清楚查询发生的原因以及如何阻止它们吗?
以下是有问题的实体:
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的延迟加载,要么它没有按预期工作。
答案 0 :(得分:0)
实体正在急切地加载,因为Printing是一个父类,其子代使用单表继承。
如果我将$ printing更改为指向叶实体,则延迟加载将按预期工作。
来自Doctrine文档, 7.2.2. Performance impact
单表继承存在一般性能考虑:如果多对一或一对一关联的目标实体是STI实体,出于性能原因,它最好是叶子实体在继承层次结构中,(即没有子类)。否则,Doctrine 不能创建此实体的代理实例,并且始终急切地加载该实体。