Я загружаю список многих объектов.
Эти объекты имеют связь «один-ко-многим» с другими объектами.
Я хочу загрузить все эти другие объекты в одном SQL-запросе (вместо одного запроса для каждого объекта в первом списке).
Как описано в документации doctrine2: http://www.doctrine-project.org/docs/orm/2.1/en/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql это должно быть возможно при загрузке «EAGER».
но он не работает, как описано.
мой код:
class User{ /** * @ORM\OneToMany(targetEntity="Address", mappedBy="user", indexBy="id", fetch="EAGER") */ protected $addresses; public function __construct(){ $this->addresses = new ArrayCollection(); } } class Address{ /** * @ORM\ManyToOne(targetEntity="User", inversedBy="addresses") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="UserId", referencedColumnName="id") * }) */ private $user; } class UserRepository{ public function findUsersWithAddresses(){ return $this->getEntityManager() ->createQuery('SELECT u FROM MyBundle:User u ORDER BY u.name ASC') ->setFetchMode('MyBundle\Entity\User', 'addresses', \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER) ->setMaxResults(10) ->getResult(); } }
Метод UserRepository :: findUsersWithAddresses () выполняет 11 SQL-запросов.
Как я могу сообщить Doctrine использовать только один SQL-запрос для загрузки адресов?
Я использую:
Текущая версия доктрины не поддерживает это.
В вопросе трекера doctrine2 есть запрос об этой функции.
Поэтому я надеюсь, что это будет реализовано в ближайшее время.
Согласно вашей ссылке:
Вы можете отметить ассоциацию « много-к-одному» или «один-к-одному», которая временно выбирается для пакетной выборки этих объектов с использованием запроса WHERE .. IN
Похоже, что текущая версия Doctrine, к сожалению, не поддерживает загрузку коллекции « один ко многим» .
Эта страница, похоже, подтверждает это предположение:
@Один ко многим
Обязательные атрибуты:
targetEntity : FQCN ссылочного целевого объекта. Может быть неквалифицированным именем класса, если оба класса находятся в одном и том же пространстве имен. ВАЖНО: Никакой ведущей обратной косой черты!
Дополнительные атрибуты:
- каскад : опция каскада
- orphanRemoval : Boolean, который указывает, следует ли удалить Doctrine, если сироты, обратные объекты OneToOne, которые не подключены к какому-либо собственному экземпляру, должны быть удалены. По умолчанию false.
- mappedBy : этот параметр указывает имя свойства в targetEntity, являющемся стороной, обладающей этим отношением. Его обязательный атрибут для обратной стороны отношения.
Аннотации @OneToMany
не содержат атрибут fetch
, а не @OneToOne
и @ManyToOne
.
Я просто заметил, что вы действительно можете получить связанные объекты, используя явный LEFT JOIN
в DQL:
SELECT u, a FROM User u LEFT JOIN u.addresses a
Используйте LEFT JOIN
, а не внутренний JOIN
, или объекты с пустой коллекцией ( User
без какого-либо Address
) будут опущены из набора результатов.
Как указано GusDeCool и webDEVILopers в комментариях, атрибут fetch
теперь поддерживается на @OneToMany
. Вышеприведенный ответ устарел.
У меня были точно такие же проблемы и обновлен модуль доктрины в Zend Framework 2 до версии 2.5, и теперь все работает нормально. Вы можете проверить мой вопрос здесь