阻止 Doctrine/Symfony 在 foreach 期间加载关联实体?(延迟加载不会发生) [英] Stop Doctrine / Symfony from loading associated entities during foreach? (lazy loading not happening)

查看:13
本文介绍了阻止 Doctrine/Symfony 在 foreach 期间加载关联实体?(延迟加载不会发生)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm seeing doctrine generating additional queries to load entities that I'm not directly accessing. I thought that lazy loading meant these associate entities wouldn't get loaded. Can you help me figure out why the queries are happening and how to stop them?

这里是有问题的实体:

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

    ...
}
class BaseInvoiceCard
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORMManyToOne(targetEntity="Invoice", inversedBy="cards")
     * @ORMJoinColumn(name="invoice_id", referencedColumnName="id")
     */
    protected $invoice;

    /**
     * @var integer
     *
     * @ORMManyToOne(targetEntity="Printing")
     * @ORMJoinColumn(name="printing_id", referencedColumnName="id")
     */
    protected $printing;

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

这行代码不会对 InvoiceCards 表产生任何查询:

This line of code doesn't cause any queries to the InvoiceCards table:

$cards = $invoice->getCards();

一旦我这样做:

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

我收到了SELECT ... FROM invoicecard",这是预期的.

I get a "SELECT ... FROM invoicecard", which is expected.

然而,对于 $cards 中的每张 $card,我也会得到一个SELECT ... FROM printing".我从不调用 $card->getPrinting().即使我在循环内什么都不做也会发生这种情况;只是运行它会导致教义运行这些查询.

However, I'm also getting a "SELECT ... FROM printing" for every $card in $cards. I never call $card->getPrinting(). This happens even if I do nothing at all inside the loop; just running it causes doctrine to run these queries.

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

Why this happening and how can I prevent it?

这是 getCards() 的代码.

This is the code for getCards().

/**
 * Get cards
 *
 * @return DoctrineCommonCollectionsCollection 
 */
public function getCards()
{
    return $this->cards;
}

编辑 2:我找到了解决这个问题的方法,尽管从长远来看它不会解决问题.我将 InvoiceCards 作为数组获取,而不是让学说将它们作为实体进行水合.

EDIT 2: I've found a workaround to this problem, though it's not going to solve things in the long run. I fetch the InvoiceCards as an array, rather than having doctrine hydrate them as entities.

$query->getArrayResult();

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

In my current situation, this technique is better anyways, since I don't require the overhead of full hydration.

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

However, the application will be working with InvoiceCards in many places, and the original issue will be still be a problem then. I feel like either I've misunderstood Doctrine's lazy loading, or it isn't working as expected.

推荐答案

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

The entities were getting eagerly loaded because Printing is a parent class whose children use single table inheritance.

如果我将 $printing 更改为指向叶实体,延迟加载将按需要工作.

If I change $printing to point to leaf entity, lazy loading works as desired.

来自 Doctrine 文档,7.2.2.性能影响

From the Doctrine docs, 7.2.2. Performance impact

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

There is a general performance consideration with Single Table Inheritance: If the target-entity of a many-to-one or one-to-one association is an STI entity, it is preferable for performance reasons that it be a leaf entity in the inheritance hierarchy, (ie. have no subclasses). Otherwise Doctrine CANNOT create proxy instances of this entity and will ALWAYS load the entity eagerly.

这篇关于阻止 Doctrine/Symfony 在 foreach 期间加载关联实体?(延迟加载不会发生)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆