web-dev-qa-db-ja.com

doctrine2は、SQLクエリが多すぎるため、フェッチモードで1対多の関連付けをロードします。

多くのエンティティのリストを読み込んでいます。
これらのエンティティには、他のエンティティと1対多の関連付けがあります。
これらの他のすべてのエンティティを(最初のリストのエンティティごとに1つのクエリではなく)1つのSQLクエリにロードしたいと思います。

Doctrine2ドキュメントに記載されているとおり: http://www.doctrine-project.org/docs/orm/2.1/en/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode -in-dql これは「EAGER」読み込みで可能になるはずです。

ただし、説明どおりには機能しません。

私のコード:

class User{
    /**
     * @ORM\OneToMany(targetEntity="Address", mappedBy="user", indexBy="id", fetch="EAGER")
     */
    protected $addresses;
    public function __construct(){
        $this->addresses = new ArrayCollection();
    }
}

class Address{
    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="UserId", referencedColumnName="id")
     * })
     */
    private $user;
}

class UserRepository{
    public function findUsersWithAddresses(){
        return $this->getEntityManager()
            ->createQuery('SELECT u FROM MyBundle:User u ORDER BY u.name ASC')
            ->setFetchMode('MyBundle\Entity\User', 'addresses', \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER)
            ->setMaxResults(10)
            ->getResult();
    }
}

UserRepository :: findUsersWithAddresses()メソッドは、11個のSQLクエリを実行します。

アドレスエンティティをロードするために1つのSQLクエリのみを使用するようにDoctrineに指示するにはどうすればよいですか?

使ってます:

  • symfony v2.0.9
  • 教義-共通2.1.4
  • doctrine-dbal 2.1.5
  • 教義2.1.5
18
ausi

doctrineの現在のバージョンはこれをサポートしていません。

Doctrine2 Issue Trackerには、これについて 機能要求 があります。

ですから、すぐに実装されることを願っています。

8
ausi

あなたのリンクによると:

多対1または1対1の関連付けを一時的にフェッチするようにマークして、WHERE ..INクエリを使用してこれらのエンティティをバッチフェッチできます。

残念ながら、現在のバージョンのDoctrineは、 1対多コレクションへの積極的な読み込みをサポートしていないようです。

このページ この仮定を確認しているようです:

@OneToMany

必要な属性:

targetEntity:参照されるターゲットエンティティのFQCN。両方のクラスが同じ名前空間にある場合は、修飾されていないクラス名にすることができます。重要:先行する円記号はありません!

オプションの属性:

  • cascade:カスケードオプション
  • orphanRemoval:孤立した、所有するインスタンスに接続されていない逆OneToOneエンティティをDoctrineで削除するかどうかを指定するブール値。デフォルトはfalseです。
  • mappedBy:このオプションは、このリレーションの所有側であるtargetEntityのプロパティ名を指定します。関係の逆側に必要な属性です。

@OneToManyアノテーションは@OneToOneおよび@ManyToOneとは対照的に、fetch属性を備えていません。


更新

DQLで明示的なLEFT JOINを使用して、 can 実際に関連エンティティをフェッチできることに気づきました。

SELECT u, a FROM User u
LEFT JOIN u.addresses a

内部のJOINではなくLEFT JOINを使用しないでください。そうしないと、コレクションが空のエンティティ(UserがないAddress)が結果セットから省略されます。

更新(2017)

コメントで GusDeCool および webDEVILopers で示されているように、fetch属性は@OneToMany現在サポートされています です。上記の回答は廃止されました。

6
Benjamin

まったく同じ問題が発生し、Zend Framework2のdoctrineモジュールをバージョン2.5に更新しましたが、すべて正常に機能しています。質問を確認できます ここ

2
Wilt