问题 在Symfony 2中急切加载相关实体


有三个实体:客户,消息,附件。

这些实体之间的关系是直截了当的:客户可以拥有许多消息,而消息可以包含许多附件。这两种关系都是“一对多”。

我在加载Customer实体的消息时告诉doctrine是懒惰的。所以 $customer->getMessages() 导致一个额外的SQL语句。没关系。

但我还为Message实体的附件定义了“EAGER”加载。

现在我希望通过调用获得的消息 $customer->getMessages() 已经加载了所有附件。但 $message->getAttachments() 仍然会为每条消息生成一个SQL语句。

这种行为有望吗?

仅供参考,我的课程除外:

Customer.php

class Customer
{
    /**
     * @ORM\OneToMany(targetEntity="Message", mappedBy="customer")
     * @ORM\OrderBy({"createdOn" = "DESC"})
     */
    private $messages;

Message.php

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

    /**
     * @ORM\ManyToOne(targetEntity="Customer", inversedBy="messages")
     * @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
     **/
    private $customer;
    /**
     * @ORM\OneToMany(targetEntity="Attachment", mappedBy="message", fetch="EAGER")
     **/
    private $attachments;

Attachment.php:

class Attachment
{

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

    /**
     * @ORM\ManyToOne(targetEntity="Message", inversedBy="attachments")
     * @ORM\JoinColumn(name="message_id", referencedColumnName="id")
     **/
    private $message;

1989
2018-02-22 12:35


起源

我认为这是在Doctrine 2.5中首次实现的。我怀疑你使用2.4? - Cerad
是的,我正在使用2.4。所以我现在必须解决这个问题。 - Jens


答案:


这对我来说听起来像预期的行为。学说文档似乎意味着渴望获取只有一个层次。

根据文件:

每当您查询具有持久关联的实体时   这些关联被映射为EAGER,它们将自动成为   与被查询的实体一起加载,因此立即加载   适用于您的应用程序。

http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#by-eager-loading

在您的情况下被查询的实体是客户,客户对消息感兴趣,因此填充了消息。但是,消息不是要查询的对象,因此附件不会被加载。


9
2018-02-22 18:50



谢谢,我希望得到一个不同的答案。至少我不必在没有错误的情况下寻找错误。 - Jens
对此不太确定。查询邮件时,附件只有一层深度。他们真的应该加载。我将不得不降低2.5并进行测试。当然,建立一个查询可能会更好。 - Cerad
@Jens Cerad是对的,如果你需要加载所有内容,你可能会更好地构建一个查询。 - Derick F


正确的代码示例可能如下所示:

注意:使用延迟加载获取消息,即主动获取带有附加查询的消息;只要从数据库中获取消息,就会自动加载引用每条消息的相应附件。

顾客

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

    /**
     * @ORM\OneToMany(targetEntity="Message", mappedBy="customer", fetch="LAZY")
     * @ORM\OrderBy({"createdOn" = "DESC"})
     */
    private $messages;

信息

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

    /**
     * @ORM\ManyToOne(targetEntity="Customer", inversedBy="messages")
     * @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
     */
    private $customer;

    /**
     * @ORM\OneToMany(targetEntity="Attchment", mappedBy="message", fetch="EAGER")
     */
    private $attachments;

附件

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

    /**
     * @ORM\ManyToONe(targetEntity="Message", inversedBy="attachments")
     * @ORM\JoinColumn(name="message_id", referencedColumnName="id")
     */
    private $message;

6
2018-03-25 11:55