如何使用symfony2中的Join限制来自doctrine的查询

时间:2014-08-14 16:17:10

标签: sql symfony join doctrine-orm symfony-2.4

我遇到了在单个查询中获取相关实体的麻烦。我使用fetch = Eager和手动查询with join.Here是我的实体

    ----------------------Store.php--------------------------------------
/**
     * @ORM\OneToMany(targetEntity="Mycomp\ProductBundle\Entity\Product", mappedBy="store_id", cascade={"all"},fetch="EXTRA_LAZY")
     *
     **/
    protected $products;


--------------------Product.php---------------------------------------
/**
     * @ORM\OneToMany(targetEntity="ProductOption", mappedBy="product", cascade={"all"},orphanRemoval=true,fetch="EAGER")
     *
     **/
    protected $options;
    /**
     * @ORM\OneToMany(targetEntity="Like", mappedBy="product", cascade={"all"},orphanRemoval=true,indexBy="id",fetch="EAGER")
     *
     **/
    protected $likes;
-------------------Like.php---------------------------------------------
/**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="likes")
     *
     **/
    private $product;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Mycomp\UserBundle\Entity\User",inversedBy="likes")
     *
     **/
    private $user;
-------------------Option.php---------------------------------------------
/**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="options")
     *
     **/
    private $product;

查询:

$qb = $em->createQueryBuilder('qb1');
        $qb->add('select', 'a', 'p', 'po', 'pl','sl')
            ->add('from', 'MycompStoreBundle:Store a')
            ->add('where', 'a.id = :store')
            ->innerJoin('a.products','p')
                ->leftJoin('p.options','po') // ***
                ->leftJoin('p.likes','pl')
            ->leftJoin('a.followers','sl')// ***
        ->setParameter('store', $id);
     $store  = $qb->getQuery()->getResult();

并在树枝

{% for product in store.0.products %}
{{ product.name }}

    {% for option in product.options %}
{{ option }}

{% endfor %}

    <div id="like-holder{{ product.id }}">  {{   like_module(product) }}</div>
{% endfor %}

对于4种产品,我会收到以下问题:

+ SELECT t0.username AS [...] FROM apps_user t0 WHERE t0.id = ? LIMIT 1
Parameters: [2]
[Display runnable query]
Time: 1.52 ms [ + Explain query ]
+ SELECT s0_.id AS id0, [...] FROM store s0_ INNER JOIN [...] WHERE (s0_.id = ?) AND s0_.dtype [...]
Parameters: ['5']
[Display runnable query]
Time: 0.89 ms [ + Explain query ]
+ SELECT t0.id AS id1, t0.name AS [...] FROM product t0 WHERE t0.store_id_id = ? AND [...]
Parameters: [5]
[Display runnable query]
Time: 0.69 ms [ + Explain query ]
+ SELECT t0.id AS id1, t0.name AS [...] FROM product_option t0 WHERE t0.product_id = ? AND [...]
Parameters: [5]
[Display runnable query]
Time: 0.46 ms [ + Explain query ]
+ SELECT t0.createdAt AS createdAt1, [...] FROM product_like t0 WHERE t0.product_id = ? AND [...]
Parameters: [5]
[Display runnable query]
Time: 0.39 ms [ + Explain query ]
+ SELECT t0.id AS id1, t0.name AS [...] FROM product_option t0 WHERE t0.product_id = ? AND [...]
Parameters: [6]
[Display runnable query]
Time: 0.54 ms [ + Explain query ]
+ SELECT t0.createdAt AS createdAt1, [...] FROM product_like t0 WHERE t0.product_id = ? AND [...]
Parameters: [6]
[Display runnable query]
Time: 0.45 ms [ + Explain query ]
+ SELECT t0.id AS id1, t0.name AS [...] FROM product_option t0 WHERE t0.product_id = ? AND [...]
Parameters: [7]
[Display runnable query]
Time: 0.42 ms [ + Explain query ]
+ SELECT t0.createdAt AS createdAt1, [...] FROM product_like t0 WHERE t0.product_id = ? AND [...]
Parameters: [7]
[Display runnable query]
Time: 0.40 ms [ + Explain query ]
+ SELECT t0.id AS id1, t0.name AS [...] FROM product_option t0 WHERE t0.product_id = ? AND [...]
Parameters: [8]
[Display runnable query]
Time: 0.37 ms [ + Explain query ]
+ SELECT t0.createdAt AS createdAt1, [...] FROM product_like t0 WHERE t0.product_id = ? AND [...]
Parameters: [8]
[Display runnable query]
Time: 0.42 ms [ + Explain query ]

为什么?正如您所看到的,我为每个产品添加了2个查询。对于喜欢和选项。

3 个答案:

答案 0 :(得分:0)

尝试更改qb代码:

$qb = $em->createQueryBuilder('qb1');
    $qb->add('select', 'a', 'p', 'po', 'pl','sl')
        ->add('from', 'MycompStoreBundle:Store a')
        ->add('where', 'a.id = :store')
        ->innerJoin('a.products','p')
            ->leftJoin('p.options','po') // ***
            ->leftJoin('p.likes','pl')
        ->leftJoin('a.followers','sl')// ***
    ->setParameter('store', $id);
 $store  = $qb->getQuery()->getResult();

为:

$qb = $em->createQueryBuilder('a');
        $qb->select('a', 'p', 'po', 'pl','sl')
            ->from('MycompStoreBundle:Store a')
            ->where('a.id = :store')
            ->innerJoin('a.products','p')
            ->leftJoin('p.options','po') // ***
            ->leftJoin('p.likes','pl')
            ->leftJoin('a.followers','sl')// ***
            ->setParameter('store', $id); 

$store  = $qb->getQuery()->getResult();

答案 1 :(得分:0)

好的,这是修复,万一有人需要它。

$qb = $em->createQueryBuilder('qb1');
        $qb->add('select', 'a,s,po,pi,us,so,si,su')
            ->add('from', 'MycompStoreBundle:Store a')
            ->add('where', 'a.id = :store')

            ->leftJoin('a.followers','so')
           ->leftJoin('a.tags','si')
            ->leftJoin('a.categories','su')

            ->Join('a.products','s')
                ->leftJoin('s.options','po')
                ->leftJoin('s.likes','pi')
                ->leftJoin('pi.user','us')

        ->setParameter('store', $id);

     $store  = $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);

然后将所有内容视为数组。

答案 2 :(得分:0)

你可以通过这样做来进一步改善这个问题。

 //Controller
 $em = $this->getDoctrine()->getManager();
 $qb = $em->createQueryBuilder();

 $store = $qb->select('a', 's', 'po', 'pi', 'us', 'so', 'si', 'su')
        ->from('MycompStoreBundle:Store', 'a')
        ->add('where', 'a.id = :id')
        ->innerJoin('a.products','s')
        ->leftJoin('a.followers','so')
        ->leftJoin('a.tags','si')
        ->leftJoin('a.categories','su')
        ->leftJoin('s.options','po')
        ->leftJoin('s.likes','pi')
        ->leftJoin('pi.user','us')
        ->setParameter(compact('id'))
        ->getQuery()
        ->getOneOrNullResult();

  return compact('store');

  //twig
  {% for product in store.products}

     {% for option in product.options %}
         {{ option }}
     {% endfor %}

     <div id="like-holder{{ product.id }}">  {{   like_module(product) }}</div>
     {% else %}
       // no results
  {% endfor %}