原则2 DQL——如何选择单向多对多查询的反面?

2022-08-30 18:31:02

我有两个类 - Page和SiteVersion,它们有很多对多的关系。只有SiteVersion知道这种关系(因为该网站是模块化的,我希望能够带走并放入SiteVersion所属的模块中)。

因此,我如何根据SiteVersion的标准选择页面?

例如,这不起作用:

SELECT p FROM SiteVersion v JOIN v.pages p WHERE v.id = 5 AND p.slug='index'

我收到错误:

[Doctrine\ORM\Query\QueryException]
[Semantical Error] line 0, col -1 near 'SELECT p FROM': Error: Cannot select entity through identification variables without choosing at least one root entity alias.

即使我可以使用此查询选择“v”。

我想我可以通过为关系引入一个类(PageToVersion类)来解决这个问题,但是有没有办法不这样做,或者让它成为双向的?


答案 1

在 Doctrine ORM 中有两种方法可以处理这个问题。最典型的一种是将条件与子查询一起使用:IN

SELECT
    p
FROM
    SitePage p
WHERE
    p.id IN(
        SELECT
            p2.id
        FROM
            SiteVersion v
        JOIN
            v.pages p2
        WHERE
            v.id = :versionId
            AND
            p.slug = :slug
    )

另一种方法是使用ORM版本2.3中引入的任意连接功能的附加连接

SELECT
    p
FROM
    SitePage p
JOIN
    SiteVersion v
WITH
    1 = 1
JOIN
    v.pages p2
WHERE
    p.id = p2.id
    AND
    v.id = :versionId
    AND
    p2.slug = :slug

这只是因为解析器的当前限制。1 = 1

请注意,导致语义错误的限制是因为水化过程从所选实体的根开始。如果没有根,水解器就没有关于如何折叠提取连接或连接结果的参考。


答案 2

我认为您还需要在查询中选择SiteVersion:

SELECT v, p FROM SiteVersion v JOIN v.pages p WHERE v.id = 5 AND p.slug='index'

您将获得一个 SiteVersion 实体数组,您可以循环访问这些实体以获取页面实体。


推荐