简体   繁体   English

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

[英]doctrine query builder join adding table twice

UPDATED at bottom: 底部更新:

I am trying to do what should be a simple join between two tables. 我正在尝试做两个表之间的简单连接。 I have a Gig table and a Venue table for a simple band site that I am building using Symfony2 (2.2). 对于使用Symfony2(2.2)构建的简单乐队站点,我有一个Gig表和一个Venue表。 It's my first time with Symfony2 and doctrine so it is possible I am going completely in the wrong direction. 这是我第一次使用Symfony2和教义,所以我可能完全朝错误的方向前进。 I have created and populated the tables with DataFixtures and have verified that the ID relationships are correct. 我已经用DataFixtures创建并填充了表,并验证了ID关系是否正确。 The problem I am getting is that the resulting DQL query has the Gig table referenced twice in the FROM section and that is causing me to get back several instances of the same record instead of the x number of records I am expecting. 我得到的问题是,生成的DQL查询在FROM部分中引用了两次Gig表,这导致我取回同一条记录的多个实例,而不是我期望的x条记录。 I don't know what I am doing wrong for that to be happening. 我不知道自己在做什么错。 Also, there may be an easier way of doing this but I am exploring all of my options since I am teaching myself Symfony2 in the process of building the site. 同样,这样做可能更简单,但是由于我在构建站点的过程中自学Symfony2,因此我正在探索所有选择。

The Gig table contains a venue_id pointing to a Venue table that is defined in the Gig entity as a ManyToOne relationship (shown below). Gig表包含一个Venue_id,指向一个Venue表,该表在Gig实体中定义为ManyToOne关系(如下所示)。 Using a doctrine findAll everything seems to work fine with the Venue class in the Gig Entity being populated correctly. 使用学说中的findAll方法,在正确填充Gig实体中的Venue类的情况下,一切似乎都可以正常工作。 I am trying to create a flat view of a few of the most recent Gigs to be displayed on the front page so I figured I would try to use a Join and include only the fields I need. 我试图创建要显示在首页上的一些最新Gig的平面视图,所以我认为我将尝试使用Join并仅包含我需要的字段。

Here is the Repository Query: 这是存储库查询:

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();

}

Here is the DQL it creates: 这是它创建的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

The Gig g2_ is my problem. Gig g2_是我的问题。 If I delete it and execute the query everything is as expected. 如果我删除它并执行查询,一切都按预期进行。 I don't know what is generating that. 我不知道是什么产生的。

The first table Gigs Entity looks like this (I am leaving out the getters and setters): 第一个表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;

The Venue table is simple and does not have any relationships defined so I will leave it out unless it is asked for. Venue表很简单,没有定义任何关系,因此除非有要求,否则我将忽略它。

Any ideas? 有任何想法吗? Thanks for any help. 谢谢你的帮助。

Andrew 安德鲁

I removed everything except what would recreate the problem and here is what I was left with: 我删除了所有东西,除了会重现问题的东西,这是我剩下的:

I simplified the repository method to: 我将存储库方法简化为:

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

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

This now generates: 现在生成:

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

There is that darn Gig g1_ problem again. 再次有该死的gig g1_问题。 I got the "Explain Query" from the Symfony profiler and it shows: 我从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

I don't pretend to know what that means but it shows both table entries with different information about how it was used. 我不假装知道这是什么意思,但是它显示了两个表条目以及有关如何使用的不同信息。

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

I found the problem. 我发现了问题。 I am not used to Doctrine and was using the ->from in a repository that did not need it since the entity was automatically related through the annotations. 我不习惯Doctrine,并且在不需要它的存储库中使用-> from,因为该实体通过注释自动关联。 My earlier query that worked was in the controller and not a repository so the ->from was necessary. 我之前的有效查询位于控制器中,而不是存储库中,因此-> from是必需的。

You are trying to do SQL. 您正在尝试执行SQL。 Doctrine is different. 主义是不同的。 Your query fetches every field. 您的查询将获取每个字段。 Doctrine prefers to fetch entities. 主义倾向于获取实体。 I think you probably want this: 我想您可能想要这样:

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

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

}

The return result is a list of entities which you can call all the specific methods directly. 返回结果是实体列表,您可以直接调用所有特定方法。 You are still welcome to specify fields with doctrine, if you want partial objects, but I've found the normal method of fetching the entire entity covers most of my needs. 如果想要部分对象,仍然欢迎您使用学说来指定字段,但是我发现获取整个实体的常规方法可以满足我的大部分需求。

This is a fundamentally different paradigm than SQL and will take some getting used to. 这是与SQL根本不同的范例,并且需要一些时间来习惯。

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

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