我有一个相当简单的产品数据库,其中一个品牌有很多产品和颜色,而产品有一种或多种颜色。
我想在一个查询中选择所有使用品牌实体的颜色和使用该特定颜色的所有产品的数量,否则我最终会在页面加载时出现30多个查询!
学说实体
品牌
class Brand
{
/**
* @ORM\Id
* @ORM\Column(type="integer", options={"unsigned"=true})
* @ORM\GeneratedValue
*/
protected $brandId;
/**
* @ORM\Column(type="string", length=45, unique=true)
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity="Product", mappedBy="brand")
*/
protected $products;
/**
* @ORM\OneToMany(targetEntity="Colour", mappedBy="brand")
*/
protected $colours;
}
产品
class Product
{
/**
* @ORM\Id
* @ORM\Column(type="integer", options={"unsigned"=true})
* @ORM\GeneratedValue
*/
protected $productId;
/**
* @ORM\Column(type="string", length=45)
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity="Brand", inversedBy="products")
* @ORM\JoinColumn(name="brandId", referencedColumnName="brandId", nullable=false)
*/
protected $brand;
/**
* @ORM\ManyToMany(targetEntity="Colour")
* @ORM\JoinTable(name="productColours",
* joinColumns={@ORM\JoinColumn(name="productId", referencedColumnName="productId")},
* inverseJoinColumns={@ORM\JoinColumn(name="colourId", referencedColumnName="colourId")}
* )
*/
protected $colours;
}
颜色
class Colour
{
/**
* @ORM\Id
* @ORM\Column(type="integer", options={"unsigned"=true})
* @ORM\GeneratedValue
*/
protected $colourId;
/**
* @ORM\Column(type="string", length=20)
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity="Brand", inversedBy="colours")
* @ORM\JoinColumn(name="brandId", referencedColumnName="brandId", nullable=false)
*/
protected $brand;
}
这在简单的SQL中这很容易......
SELECT c.*, b.*, count(p.productId) as productCount
FROM colours c
INNER JOIN brands b ON c.brandId = b.brandId
LEFT JOIN productColours pc ON pc.colourId = c.colourId
LEFT JOIN products p ON p.productId = pc.productId
GROUP BY c.colourId
在Doctrine中我无法找到解决这个问题的办法,如果没有将双向映射添加到颜色中,我真的不希望产品数量。
我当前的查询看起来像这样(这不起作用,因为没有c.products映射)。
$query = $this->getEntityManager()->createQueryBuilder()
->select(
'c AS colour',
'b AS brand',
'COUNT(DISTINCT p.productId) AS productCount'
)
->from('Colour', 'c')
->innerJoin('c.brand', 'b')
->leftJoin('c.products', 'p');
另外假设上面的内容不会将品牌映射到颜色实体,所以我不能去$colour->getBrand()
?
答案 0 :(得分:0)
您可以使用doctrine运行本机SQL查询来实现您的目标。请在此处查看示例:http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html
第二个选项是 使用 双向关联。如果您关心性能,则可以启用LAZY
或EXTRA_LAZY
获取模式。因此,如果有的话,表现将受到最小的影响。
有关extra lazy
个关联的更多信息:http://doctrine-orm.readthedocs.org/en/latest/tutorials/extra-lazy-associations.html
默认情况下,教条关联被认为是懒惰的。这意味着实体仅在使用时才会完全加载(即属性访问,搜索等)。
extra lazy
提取模式会减少触发完整实体水合作用的方法数量。