0

底部更新:

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

Gig 表包含一个venue_id,指向一个在Gig 实体中定义为ManyToOne 关系的Venue 表(如下所示)。使用学说 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

我不假装知道这意味着什么,但它显示了两个表条目,其中包含有关其使用方式的不同信息。

4

3 回答 3

0

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

于 2013-04-28T06:33:47.493 回答
0

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

于 2013-04-28T12:00:27.727 回答
0

您正在尝试执行 SQL。教义不同。您的查询获取每个字段。Doctrine 更喜欢获取实体。我想你可能想要这个:

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

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

}

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

这是一个与 SQL 完全不同的范例,需要一些时间来适应。

于 2013-04-28T19:58:53.840 回答