在 Symfony 2 中预先加载相关实体

Eager loading of related entity in Symfony 2

存在三个实体:客户、消息、附件。

这些实体之间的关系很简单:一个客户可以有很多消息,一个消息可以有很多附件。两个关系都是"one-to-many".

我告诉学说在加载客户实体的消息时要懒惰。因此 $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;

这对我来说听起来像是预期的行为。 doctrine 文档似乎暗示 eager fetching 只有一层深。

根据文档:

Whenever you query for an entity that has persistent associations and these associations are mapped as EAGER, they will automatically be loaded together with the entity being queried and is thus immediately available to your application.

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

在您的案例中被查询的实体是客户,并且客户渴望消息,因此消息被填充。但是,消息不是被查询的对象,因此不会加载附件。

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

NOTE: fetch message with lazy loading, i.e. get messages with additional query proactively; as long as the messages are fetched from database, the corresponding attachments referenced to each message will be loaded automatically.

客户

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;