【问题标题】:How to JOIN without relational table in Symfony Doctrine with QueryBuilder between 2 entities如何在 Symfony Doctrine 中使用 QueryBuilder 在 2 个实体之间加入无关系表
【发布时间】:2014-02-02 16:35:15
【问题描述】:

我有一个与实体类别相关的实体视频,我需要使用 Doctrine QueryBuilder 运行此 SQL,这样我可以获得所有视频中最常用的类别 (1000+):

    SELECT c.*
    FROM Video v
    INNER JOIN video_category vc ON vc.video_id = v.id
    INNER JOIN Category c ON vc.category_id = c.id
    GROUP BY c.id
    HAVING COUNT(v.id) > 1000
    ORDER BY c.name ASC;

我的查询构建器:

    $queryBuilder = $this->getEntityManager()
        ->createQueryBuilder()
        ->select('c')
        ->from('AcmeVideoBundle:Video', 'v')
        // Can Doctrine join itself silently with relational info in the Entities?
        ->join('AcmeCategoryBundle:Category', 'c', Expr\Join::WITH, 'v.id = c.id')
        ->groupBy('c.id')
        ->having('COUNT(v.id) > 1000')
        ->orderBy('c.name', 'ASC')
        ->getQuery();

但是queryBuilder输出的SQL查询是这样的:

    SELECT c0_.id AS id0, c0_.NAME AS name1 
    FROM Video v1_ 
    INNER JOIN Category c0_ ON (v1_.id = c0_.id) 
    GROUP BY c0_.id 
    HAVING COUNT(v1_.id) > 1000
    ORDER BY c0_.NAME ASC

没有关系表(video_category)

实体映射:

    /**
     * Video
     *
     * @ORM\Table
     * @ORM\Entity(repositoryClass="Acme\VideoBundle\Entity\VideoRepository")
     */
    class Video
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;

        /**
         * @ORM\ManyToMany(targetEntity="Acme\CategoryBundle\Entity\Category", cascade={"persist"})
         */
        private $category;

        // More fields, getters and setters etc...
    }

    /**
     * Category
     *
     * @ORM\Table
     * @ORM\Entity(repositoryClass="Acme\CategoryBundle\Entity\CategoryRepository")
     */
    class Category
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;

        /**
         * @ORM\Column(type="string", length=255)
         */
        private $name;

        // More fields, getters and setters etc...
    }

我怎样才能使用关系表来运行与学说Querybuilder的原始SQL查询?我错过了什么?

INFO:当我 findBy{field}、persist、flush、clear 在所有实体上工作正常时,Doctrine 关系正常,我有一个 Video、Category 和 video_category 表正常,原始 SQL 查询工作正常。

【问题讨论】:

  • 您是否尝试像使用 JOIN 一样声明关系表?
  • 是的:[语义错误]第 0 行,'video_category' 附近的第 54 列:错误:未定义类'video_category'。

标签: php mysql sql symfony doctrine-orm


【解决方案1】:
   // Can Doctrine join itself silently with relational info in the Entities?
    ->join('AcmeCategoryBundle:Category', 'c', Expr\Join::WITH, 'v.id = c.id')

是的!事实上,这是使用诸如 Doctrine 2 这样的 ORM 的主要原因之一。

试试:

->leftJoin('v.category','c')

虽然奇怪的是该手册似乎没有连接示例,但该手册更详细地介绍了它。因此,常见的混淆。

http://docs.doctrine-project.org/en/latest/reference/query-builder.html

您可能不知道这一点,但联合国已通过一项决议,禁止使用别名缩写。为了安全起见,请尝试:

$queryBuilder = $this->getEntityManager()
    ->createQueryBuilder()
    ->addSelect('category')
    ->from('AcmeVideoBundle:Video', 'video')
    ->leftJoin('video.category', 'category')
    ->groupBy('category.id')
    ->having('COUNT(video.id) > 1000')
    ->orderBy('category.name', 'ASC')
    ->getQuery();

【讨论】:

  • 我喜欢别名的全称,我把简短的版本放在StackOverflow中澄清例子,是众所周知的观点相同的人!在过去的几个小时里,我得到了与 ->select() 和 ->join() / innerJoin() 的其他组合相同的异常:[Semantical Error] line 0, col -1 near 'SELECT category': Error: Cannot select entity through在不选择至少一个根实体别名的情况下识别变量。我用了你回答的代码:/
【解决方案2】:

好的,解决了,问题是实体没有完全映射到多对多双向关系。

实体现在是:

    class Video
    {
        /**
         * @var ArrayCollection
         *
         * @ORM\ManyToMany(targetEntity="Acme\CategoryBundle\Entity\Category", inversedBy="video") // Note the inversedBy key
         */
        private $category;
    }

    class Category
    {
        /**
         * @var Video
         *
         * @ORM\ManyToMany(targetEntity="Acme\VideoBundle\Entity\Video", mappedBy="category") // Again the inversed
         */
        private $video; // New field for bidirectional ManyToMany
    }

最后的 QueryBuilder 工作(现在有完整的别名版本:P):

    $queryBuilder = $this->getEntityManager()
        ->createQueryBuilder()
        ->select('category')
        ->from('AcmeCategoryBundle:Category', 'category')
        ->join('category.video', 'video')
        ->groupBy('category.id')
        ->having('COUNT(video.id) > 1000')
        ->orderBy('category.name', 'ASC')
        ->getQuery();

最好的问候

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多