我有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 ▶}
]
答案 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
将结果作为数组而不是对象获取,尤其是因为您有很多查询。