原则查询生成器连接添加表两次
已更新在底部:原则查询生成器连接添加表两次
我想要做什么应该是两个表之间的简单连接。我使用Symfony2(2.2)构建了一个简单的乐队网站,其中有一个Gig桌子和一个Venue桌子。这是我第一次使用Symfony2和教义,所以我可能完全走错了方向。我用DataFixtures创建并填充了表,并验证了ID关系是正确的。我得到的问题是生成的DQL查询具有在FROM部分中引用两次的Gig表,并且这导致我找回相同记录的多个实例,而不是我期望的x个记录数。我不知道我在做什么错,因为这会发生。另外,这样做可能更简单,但我正在探索我的所有选项,因为我在构建网站的过程中自学Symfony2。
Gig表包含一个指向Venue表的venue_id,该表在Gig实体中定义为ManyToOne关系(如下所示)。使用教条查找所有的一切似乎都正常工作正常填充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
的千兆g2_是我的问题。如果我删除它并执行查询,一切都如预期。我不知道是什么造成的。
第一台演出实体看起来是这样的(我离开了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;
的地点表很简单,没有定义,因此任何关系,我会离开它,除非它被要求。
任何想法?谢谢你的帮助。
安德鲁
我删除了除你会重现问题,这里的一切是什么我留下了:
我简化了存储库的方法:
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
还有那个问题g1 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
我不假装知道是什么意思,但它显示了它是如何使用不同的信息都表项。
我发现了这个问题。我不习惯教义,并且在不需要它的存储库中使用 - >,因为实体通过注释自动关联。我以前的查询工作是在控制器中,而不是一个存储库,所以 - > from是必要的。
如果您已经拥有包含外键的“场地”,那么“venueId”的用法是什么?
您正在尝试执行SQL。学说是不同的。您的查询提取每个字段。学说更喜欢获取实体。我想你也许想要这个:
public function getGigsWithLimit($maxGigs)
{
$qb = $this->createQueryBuilder('g')
->leftJoin('g.venue', 'v')
->orderBy('g.gigDate', 'DESC')
->setMaxResults($maxGigs);
return $qb->getQuery()->getResult();
}
返回结果是实体的名单,你可以直接调用所有的具体方法。如果您想要部分对象,仍然欢迎您指定带有教义的字段,但我发现提取整个实体的常规方法可以满足我的大多数需求。
这是一个与SQL根本不同的范例,需要一些习惯。
我对此很好奇。它似乎工作正常,但我没有意识到外键是自动创建的。我将尝试删除它。谢谢。 – akwebb1 2013-04-28 12:01:19