Symfony2 ManyToMany在一个查询中

时间:2017-06-04 19:40:15

标签: php mysql symfony doctrine-orm entity-relationship

我有2个与ManyToMany相关的实体

class Product
{

/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=100, unique=true)
 */
private $name;

/**
 * @ORM\ManyToMany(targetEntity="ProductTransfer", inversedBy="product")
 * @ORM\JoinTable(name="products_transfers")
 */
private $transfers;

和第二个

class ProductTransfer
{
/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var int
 *
 * @ORM\Column(name="stock_from_id", type="integer")
 */
private $stockFromId;

/**
 * @var int
 *
 * @ORM\Column(name="stock_to_id", type="integer")
 */
private $stockToId;

/**
 * @var int
 *
 * @ORM\Column(name="product_id", type="integer")
 */
private $productId;

/**
 * @ORM\ManyToMany(targetEntity="Product",mappedBy="transfers")
 */
private $product;

一切都很好,附加表是由Doctrine创建的 但是当我试图从ProductTransfers获取所有行时,我在分析器中看到每行需要一个带有2个连接的查询。
因此,对于5000个产品,它将是非常多的查询。

有没有办法在“干净​​SQL”中的一个查询中获取所有这些内容? 如果无法用Doctrine做到这一点,那么实现这一目标的最佳方法是什么?

像:

SELECT * FROM product_transfer pt
LEFT JOIN products_transfers pts ON pt.product_id=pts.product_id
LEFT JOIN product p ON pts.product_id=p.id;

编辑: 在存储库中创建方法

public function loadTransfersByStock($stockId)
{

    $q = $this->getEntityManager()
        ->createQuery(
            'SELECT pt,p FROM AppBundle:ProductTransfer pt
            LEFT JOIN AppBundle:Product p WITH pt.productId=p.id
            WHERE pt.stockToId = :stockId'
        );

    return $q->setParameter('stockId', $stockId)->getResult();
}

然后结果是

ProductsController.php on line 495:
array:3 [▼
  0 => ProductTransfer {#1071 ▶}
  1 => Product {#1084 ▶}
  2 => ProductTransfer {#1099 ▶}
]

2 个答案:

答案 0 :(得分:0)

默认情况下,Doctrine在对象关系中使用延迟加载 - 只有在您尝试访问它们时才会加载关系的行。如果您知道自己需要所有相关行,请尝试更改为急切提取。

/**
 * @ORM\ManyToMany(targetEntity="ProductTransfer", inversedBy="product", fetch="EAGER")
 * @ORM\JoinTable(name="products_transfers")
 */

答案 1 :(得分:0)

当您在存储库中编写类似的查询时,您正在跳过教义“希望”您编写它的方式。所以不是那样,我会做这样的事情:

//ProductTransferRepository.php
$qb = $this->createQueryBuilder('pt');
$qb
    ->select('pt, p') // here you can choose the columns you want if you don't need everything from both tables
    ->leftJoin('pt.product', 'p')
    ->where('pt.stockToId = :stockId')
    ->setParameter('stockId', $stockId)
;
return $qb
    ->getQuery()
    ->getArrayResult()
;

使用getArrayResult将结果作为数组而不是对象获取,尤其是因为您有很多查询。