繁体   English   中英

学问查询生成器两次加入添加表

[英]doctrine query builder join adding table twice

底部更新:

我正在尝试做两个表之间的简单连接。 对于使用Symfony2(2.2)构建的简单乐队站点,我有一个Gig表和一个Venue表。 这是我第一次使用Symfony2和教义,所以我可能完全朝错误的方向前进。 我已经用DataFixtures创建并填充了表,并验证了ID关系是否正确。 我得到的问题是,生成的DQL查询在FROM部分中引用了两次Gig表,这导致我取回同一条记录的多个实例,而不是我期望的x条记录。 我不知道自己在做什么错。 同样,这样做可能更简单,但是由于我在构建站点的过程中自学Symfony2,因此我正在探索所有选择。

Gig表包含一个Venue_id,指向一个Venue表,该表在Gig实体中定义为ManyToOne关系(如下所示)。 使用学说中的findAll方法,在正确填充Gig实体中的Venue类的情况下,一切似乎都可以正常工作。 我试图创建要显示在首页上的一些最新Gig的平面视图,所以我认为我将尝试使用Join并仅包含我需要的字段。

这是存储库查询:

public function getGigsWithLimit($maxGigs)
{
    $qb = $this->createQueryBuilder('b')
        ->select('
            g.gigDate,
            g.startTime,
            g.endTime,
            g.message1 as gig_message1,
            g.message2 as gig_message2,
            g.url,
            v.name,
            v.address1,
            v.address2,
            v.city,
            v.state,
            v.zip,
            v.phone,
            v.url as venue_url,
            v.message1 as venue_message1,
            v.message2 as venue_message2,
            v.message3 as venue_message3'
        )
        ->from('WieldingBassBundle:Gig', 'g')
        ->leftJoin('g.venue', 'v')
        ->orderBy('g.gigDate', 'DESC')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();

}

这是它创建的DQL:

SELECT 
  g0_.id AS id0, 
  g0_.gig_date AS gig_date1, 
  g0_.start_time AS start_time2, 
  g0_.end_time AS end_time3, 
  g0_.message1 AS message14, 
  g0_.message2 AS message25, 
  g0_.url AS url6, 
  v1_.name AS name7, 
  v1_.address1 AS address18, 
  v1_.address2 AS address29, 
  v1_.city AS city10, 
  v1_.state AS state11, 
  v1_.zip AS zip12, 
  v1_.phone AS phone13, 
  v1_.url AS url14, 
  v1_.message1 AS message115, 
  v1_.message2 AS message216, 
  v1_.message3 AS message317 
FROM 
  Gig g2_, 
  Gig g0_ 
LEFT JOIN 
  Venue v1_ ON g0_.venue_id = v1_.id 
LIMIT 
  6

Gig g2_是我的问题。 如果我删除它并执行查询,一切都按预期进行。 我不知道是什么产生的。

第一个表Gigs Entity看起来像这样(我省略了getter和setter):

/**
 * Gig
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Wielding\BassBundle\Entity\GigRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Gig
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="gig_date", type="date")
 */
private $gigDate;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="start_time", type="datetime")
 */
private $startTime;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="end_time", type="datetime")
 */
private $endTime;

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

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

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

/**
 * @var integer
 *
 * @ORM\Column(name="venue_id", type="integer")
 */
private $venueId;

/**
 * @ORM\Column(type="datetime")
 */
protected $created;

/**
 * @ORM\Column(type="datetime")
 */
protected $updated;


/**
 * @ORM\ManyToOne(targetEntity="Venue", cascade="persist")
 * @ORM\JoinColumn(name="venue_id", referencedColumnName="id")
 */
protected $venue;

Venue表很简单,没有定义任何关系,因此除非有要求,否则我将忽略它。

有任何想法吗? 谢谢你的帮助。

安德鲁

我删除了所有东西,除了会重现问题的东西,这是我剩下的:

我将存储库方法简化为:

public function getGigsWithLimit2($maxGigs)
{
    $qb = $this->createQueryBuilder('a')
        ->select('g.id')
        ->from('WieldingBassBundle:Gig', 'g')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();
}

现在生成:

SELECT 
  g0_.id AS id0 
FROM 
  Gig g1_, 
  Gig g0_ 
LIMIT 
  6

再次有该死的gig g1_问题。 我从Symfony探查器获得了“解释查询”,它显示:

id  select_type table   type    possible_keys   key key_len ref rows        Extra
1   SIMPLE  g1_ index       IDX_ED7D664240A73EBA    4       9     Using index
1   SIMPLE  g0_ index       IDX_ED7D664240A73EBA    4       9    Using index; Using join buffer

我不假装知道这是什么意思,但是它显示了两个表条目以及有关如何使用的不同信息。

如果您已经获得包含外键的“ venue”,那么“ venueId”有什么用?

我发现了问题。 我不习惯Doctrine,并且在不需要它的存储库中使用-> from,因为该实体通过注释自动关联。 我之前的有效查询位于控制器中,而不是存储库中,因此-> from是必需的。

您正在尝试执行SQL。 主义是不同的。 您的查询将获取每个字段。 主义倾向于获取实体。 我想您可能想要这样:

public function getGigsWithLimit($maxGigs)
{
    $qb = $this->createQueryBuilder('g')
        ->leftJoin('g.venue', 'v')
        ->orderBy('g.gigDate', 'DESC')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();

}

返回结果是实体列表,您可以直接调用所有特定方法。 如果想要部分对象,仍然欢迎您使用学说来指定字段,但是我发现获取整个实体的常规方法可以满足我的大部分需求。

这是与SQL根本不同的范例,并且需要一些时间来习惯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM