doctrine2 carga asociaciones de uno a muchos con el modo fetch impaciente usando demasiadas consultas SQL

Estoy cargando una lista de muchas entidades.
Estas entidades tienen una asociación uno a muchos con otras entidades.
Quiero cargar todas estas otras entidades en una sola consulta SQL (en lugar de una consulta para cada entidad en la primera lista).

Como se describe en la documentación de doctrine2: http://www.doctrine-project.org/docs/orm/2.1/en/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql esto debería ser posible con la carga “EAGER”.

pero no funciona como se describe.

mi código:

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(); } } 

El método UserRepository :: findUsersWithAddresses () ejecuta 11 consultas SQL.

¿Cómo puedo decirle a Doctrine que use solo una consulta SQL para cargar las entidades de dirección?

Estoy usando:

  • symfony v2.0.9
  • doctrine-común 2.1.4
  • doctrine-dbal 2.1.5
  • doctrine 2.1.5

La versión actual de la doctrine no es compatible con esto.

Hay una solicitud de función sobre esto en el rastreador de problemas de doctrine2.

Así que espero que se implemente pronto.

De acuerdo con tu enlace:

Puede marcar una asociación de varios a uno o de uno a uno como capturados temporalmente para buscar estas entidades en batch utilizando una consulta WHERE .. IN

Parece que la versión actual de Doctrine no admite una carga ansiosa en una colección de uno a muchos , desafortunadamente.

Esta página parece confirmar esta suposición:

@Uno a muchos

Atributos requeridos:

targetEntity : FQCN de la entidad objective referenciada. Puede ser el nombre de clase no calificado si ambas clases están en el mismo espacio de nombres. IMPORTANTE: ¡Sin barras diagonales inversas!

Atributos opcionales:

  • cascada : Opción Cascade
  • orphanRemoval : Boolean que especifica si Doctrine debe eliminar huérfanos, entidades OneToOne inversas que no están conectadas a ninguna instancia propietaria. El valor predeterminado es falso.
  • mappedBy : esta opción especifica el nombre de la propiedad en el targetEntity que es el lado propietario de esta relación. Es un atributo obligatorio para el lado inverso de una relación.

La anotación @OneToMany no tiene un atributo fetch , a diferencia de @OneToOne y @ManyToOne .


Actualizar

Me acabo de dar cuenta de que puedes buscar realmente las entidades relacionadas, usando un LEFT JOIN explícito en DQL:

 SELECT u, a FROM User u LEFT JOIN u.addresses a 

Utilice una LEFT JOIN , y no una JOIN interna, o las entidades con una colección vacía ( User sin Address ) se omitirán del conjunto de resultados.

Actualización (2017)

Como señalaron GusDeCool y webDEVILopers en los comentarios, el atributo de fetch ahora es compatible con @OneToMany . La respuesta anterior ahora está obsoleta.

Tenía exactamente los mismos problemas y actualicé mi módulo de doctrine en Zend Framework 2 a la versión 2.5 y ahora todo está funcionando bien. Puedes consultar mi pregunta aquí