0

下部に更新:

2 つのテーブル間の単純な結合を実行しようとしています。Symfony2 (2.2) を使用して構築している単純なバンド サイト用のギグ テーブルと会場テーブルがあります。Symfony2 と doctrine を使用するのは初めてなので、完全に間違った方向に進んでいる可能性があります。テーブルを作成して DataFixtures を設定し、ID の関係が正しいことを確認しました。私が得ている問題は、結果の DQL クエリの FROM セクションで Gig テーブルが 2 回参照されていることです。これにより、期待している x 数のレコードではなく、同じレコードの複数のインスタンスが返されます。それが起こっているために何が間違っているのかわかりません。また、これを行うためのより簡単な方法があるかもしれませんが、サイトを構築する過程で Symfony2 を独学しているため、すべてのオプションを検討しています。

Gig テーブルには、Gig エンティティで ManyToOne 関係として定義されている Venue テーブルを指すvenue_id が含まれています (以下を参照)。doctrine findAll を使用すると、Gig Entity の Venue クラスが正しく設定されているため、すべてが正常に機能するようです。フロントページに表示される最新のギグのいくつかのフラットビューを作成しようとしているので、結合を使用して必要なフィールドのみを含めようと考えました。

リポジトリクエリは次のとおりです。

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 は次のようになります (ゲッターとセッターは省略しています)。

/**
 * 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 プロファイラーから「Explain Query」を取得したところ、次のように表示されました。

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

問題が見つかりました。私はDoctrineに慣れておらず、エンティティが注釈を通じて自動的に関連付けられたため、必要のないリポジトリで ->from を使用していました。機能した以前のクエリはリポジトリではなくコントローラーにあったため、 ->from が必要でした。

于 2013-04-28T12:00:27.727 に答える
0

外部キーを含む「venue」を既に取得している場合、「venueId」の使用は何ですか?

于 2013-04-28T06:33:47.493 に答える
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();

}

返される結果は、すべての特定のメソッドを直接呼び出すことができるエンティティのリストです。部分的なオブジェクトが必要な場合は、doctrine でフィールドを指定することは引き続き歓迎されますが、エンティティ全体をフェッチする通常の方法で私のニーズのほとんどがカバーされることがわかりました。

これは SQL とは根本的に異なるパラダイムであり、慣れるまでに時間がかかります。

于 2013-04-28T19:58:53.840 に答える