2015-02-22 4 views
7

Существует три объекта: Клиент, Сообщения, Приложения.Желаемая загрузка связанного объекта в Symfony 2

Связь между этими объектами прямолинейна: у клиента может быть много сообщений, а сообщение может иметь много вложений. Оба отношения - «один ко многим».

Я сказал учению, чтобы он ленился при загрузке сообщений для объекта Customer. Итак, $customer->getMessages() приводит к дополнительному запросу SQL. Хорошо.

Но я также определил загрузку «EAGER» для вложений для объекта Message.

Теперь я ожидал, что сообщения, которые я получаю, позвонив по телефону $customer->getMessages(), уже загружены со всеми их вложениями. Но $message->getAttachments() все еще вызывает одну инструкцию SQL для каждого сообщения.

Ожидается ли такое поведение?

Просто для справки, excepts из моих классов:

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; 
+0

Я думаю, что это была впервые реализована в Учении 2.5. Я подозреваю, что вы используете 2.4? – Cerad

+0

Да, я использую 2.4. Поэтому сейчас я должен буду решить эту проблему. – Jens

ответ

6

Это звучит как exp для меня. Документация доктрины, по-видимому, подразумевает, что нетерпеливая выборка только на один уровень.

Согласно документации:

Всякий раз, когда вы запрашиваете объект, который имеет постоянные ассоциации и эти ассоциации отображаются в EAGER, они будут автоматически загружен вместе с объектом и запрашиваемым таким образом, немедленно доступны для вашего приложения.

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

Объект выполняется запрос в вашем случае клиент и клиент готов на сообщения поэтому сообщения заполняются. Сообщения, однако, не являются объектом запроса, поэтому вложения не загружаются.

+0

Спасибо, я надеялся на другой ответ. По крайней мере, мне не нужно искать ошибку, где ее нет. – Jens

+0

Не так уверен в этом. Когда сообщения запрашиваются, вложения - только один уровень. Они действительно должны загружаться. Мне придется сбить 2.5 и запустить тест. Конечно, вам может быть лучше просто создать запрос. – Cerad

+0

@ Jens Cerad прав, что вам, вероятно, намного лучше строить запрос, если вам нужно все загруженное. –

3

правильный пример кода может быть как следующий:

Примечание: получать сообщение с отложенной загрузки, то есть получать сообщения с дополнительным запросом проактивно; до тех пор, пока сообщения будут получены из базы данных, соответствующие вложения, на которые ссылаются каждое сообщение, будут загружаться автоматически.

Клиент

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; 

Attachment

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; 
Смежные вопросы