Skip to content

Commit 40a0964

Browse files
authored
Merge pull request #11289 from themasch/reproduce-issue-11154-composite-key-eager-fetch-one
Do not use batch loading for collections with composite identifier
2 parents 08a9e60 + 3e3c023 commit 40a0964

File tree

4 files changed

+140
-2
lines changed

4 files changed

+140
-2
lines changed

src/UnitOfWork.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3166,9 +3166,9 @@ public function createEntity($className, array $data, &$hints = [])
31663166

31673167
if ($hints['fetchMode'][$class->name][$field] === ClassMetadata::FETCH_EAGER) {
31683168
$isIteration = isset($hints[Query::HINT_INTERNAL_ITERATION]) && $hints[Query::HINT_INTERNAL_ITERATION];
3169-
if (! $isIteration && $assoc['type'] === ClassMetadata::ONE_TO_MANY) {
3169+
if ($assoc['type'] === ClassMetadata::ONE_TO_MANY && ! $isIteration && ! $targetClass->isIdentifierComposite) {
31703170
$this->scheduleCollectionForBatchLoading($pColl, $class);
3171-
} elseif (($isIteration && $assoc['type'] === ClassMetadata::ONE_TO_MANY) || $assoc['type'] === ClassMetadata::MANY_TO_MANY) {
3171+
} else {
31723172
$this->loadCollection($pColl);
31733173
$pColl->takeSnapshot();
31743174
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\EagerFetchedCompositeOneToMany;
6+
7+
use Doctrine\Common\Collections\ArrayCollection;
8+
use Doctrine\Common\Collections\Collection;
9+
use Doctrine\ORM\Mapping as ORM;
10+
11+
/**
12+
* @ORM\Entity
13+
* @ORM\Table(name="eager_composite_join_root")
14+
*/
15+
class RootEntity
16+
{
17+
/**
18+
* @ORM\Id
19+
* @ORM\Column(type="integer", nullable=false)
20+
*
21+
* @var int|null
22+
*/
23+
private $id = null;
24+
25+
/**
26+
* @ORM\Id
27+
* @ORM\Column(type="string", nullable=false, name="other_key")
28+
*
29+
* @var string
30+
*/
31+
private $otherKey;
32+
33+
/**
34+
* @ORM\OneToMany(mappedBy="root", targetEntity=SecondLevel::class, fetch="EAGER")
35+
*
36+
* @var Collection<int, SecondLevel>
37+
*/
38+
private $secondLevel;
39+
40+
public function __construct(int $id, string $other)
41+
{
42+
$this->otherKey = $other;
43+
$this->secondLevel = new ArrayCollection();
44+
$this->id = $id;
45+
}
46+
47+
public function getId(): ?int
48+
{
49+
return $this->id;
50+
}
51+
52+
public function getOtherKey(): string
53+
{
54+
return $this->otherKey;
55+
}
56+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\EagerFetchedCompositeOneToMany;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ORM\Entity
11+
* @ORM\Table(name="eager_composite_join_second_level", indexes={
12+
* @ORM\Index(name="root_other_key_idx", columns={"root_other_key", "root_id"})
13+
* })
14+
*/
15+
class SecondLevel
16+
{
17+
/**
18+
* @ORM\Id
19+
* @ORM\Column(type="integer", nullable=false)
20+
*
21+
* @var int|null
22+
*/
23+
private $upperId;
24+
25+
/**
26+
* @ORM\Id
27+
* @ORM\Column(type="string", nullable=false, name="other_key")
28+
*
29+
* @var string
30+
*/
31+
private $otherKey;
32+
33+
/**
34+
* @ORM\ManyToOne(targetEntity=RootEntity::class, inversedBy="secondLevel")
35+
* @ORM\JoinColumns({
36+
* @ORM\JoinColumn(name="root_id", referencedColumnName="id"),
37+
* @ORM\JoinColumn(name="root_other_key", referencedColumnName="other_key")
38+
* })
39+
*
40+
* @var RootEntity
41+
*/
42+
private $root;
43+
44+
public function __construct(RootEntity $upper)
45+
{
46+
$this->upperId = $upper->getId();
47+
$this->otherKey = $upper->getOtherKey();
48+
$this->root = $upper;
49+
}
50+
51+
public function getId(): ?int
52+
{
53+
return $this->id;
54+
}
55+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional;
6+
7+
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\RootEntity;
8+
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\SecondLevel;
9+
use Doctrine\Tests\OrmFunctionalTestCase;
10+
11+
final class EagerFetchOneToManyWithCompositeKeyTest extends OrmFunctionalTestCase
12+
{
13+
/** @ticket 11154 */
14+
public function testItDoesNotThrowAnExceptionWhenTriggeringALoad(): void
15+
{
16+
$this->setUpEntitySchema([RootEntity::class, SecondLevel::class]);
17+
18+
$a1 = new RootEntity(1, 'A');
19+
20+
$this->_em->persist($a1);
21+
$this->_em->flush();
22+
23+
$this->_em->clear();
24+
25+
self::assertCount(1, $this->_em->getRepository(RootEntity::class)->findAll());
26+
}
27+
}

0 commit comments

Comments
 (0)