[DDC-2245] EntityManager#getReference returns NULL on SINGLE_TABLE inheritance Created: 15/Jan/13 Updated: 20/Jan/13 Resolved: 20/Jan/13 |
|
| Status: | Resolved |
| Project: | Doctrine 2 - ORM |
| Component/s: | ORM |
| Affects Version/s: | 2.3.2 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major |
| Reporter: | Masaki Fujimoto | Assignee: | Benjamin Eberlei |
| Resolution: | Invalid | Votes: | 0 |
| Labels: | None | ||
| Description |
|
When EntityManager#getReference is called with SINGLE_TABLE inherited entity, it tries to get a loaded entity by calling unitOfWork->tryGetById($sortedId, $class->rootEntityName). The call may return an entity object of root entity class which is not what is asked, then it ends up returning NULL instead of going further. |
| Comments |
| Comment by Marco Pivetta [ 15/Jan/13 ] |
|
This looks quite serious. On the other side, `getReference` should probably call `find` on inheritances. Do you have any example code for this? |
| Comment by Masaki Fujimoto [ 15/Jan/13 ] |
|
Yes, following line returns NULL with entity classes I have(it's a part of Symfony2 project):
$entity = $em->getRepository('EnjoitechBaseBundle:MCode')->find('01') // load an entity of root entity class
$ref = $em->getReference('Enjoitech\BaseBundle\Entity\MCodeModule', '01'); // try to get reference of sub entity with same ID, this return NULL
// $ref => NULL
// MCode.php
<?php
namespace Enjoitech\BaseBundle\Entity;
use \PDO;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="M_CODE")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="CLASS", type="string", length=2)
* @ORM\DiscriminatorMap({"00" = "MCode", "01" = "MCodeModule"})
*/
class MCode
{
/**
* @ORM\Id
* @ORM\Column(type="string", length=2)
*/
protected $CODE;
/**
* @ORM\Column(type="string", length=128)
*/
protected $DESCRIPTION;
public function getCODE()
{
return $this->CODE;
}
}
/**
* @ORM\Entity
*/
class MCodeModule extends MCode
{
}
I also saw a post that mentioned a similar/same issue at https://groups.google.com/forum/#!msg/doctrine-user/55IkFJlADh8/79QpCIH1Ag4J |
| Comment by Benjamin Eberlei [ 20/Jan/13 ] |
|
This is the correct behavior, if you fetch MCodeModule and its "only" a MCode, then returning null is correct, because you assume to retrieve a MCodeModule or nothing. |
| Comment by Masaki Fujimoto [ 20/Jan/13 ] |
|
I am not assuming getReference is supposed to fetch/retrieve/load anything. Shouldn't it return a reference to an entity object even the target entity hasn't been loaded yet? getReference won't return null because you'll never know if the entity exists in database in my opinion. |
| Comment by Marco Pivetta [ 20/Jan/13 ] |
|
Masaki Fujimoto that doesn't work with inheritances, since you will need to query the discriminator column to know what object to instantiate |
| Comment by Masaki Fujimoto [ 20/Jan/13 ] |
|
I see, thanks for clarifying that. That was what I thought as far as I see in code; $sortedId array doesn't include discriminator column and value at all. So basically getReference won't guarantee its behaviour when the target is inheritances correct? I should rather use find() maybe. Will you keep that policy for future? I also encountered few more issues related to SINGLE_TABLE inheritance. something like find() returns entities of other inheritance class that were loaded earlier. I needed to clear entityManager each time before I get entities of another subclassed of MCode. I guess there may be same sort of implementation without considering discriminator column. Are these all known issues or it's just how it is intended? |
| Comment by Marco Pivetta [ 20/Jan/13 ] |
|
Masaki Fujimoto repeated calls to `find` give you the same instances for same identifiers. If you changed something, you'll need to `clear`, though it looks like you're doing a lot of unconventional stuff in there. I think that on STI/JTI, `getReference` could short-circuit to `find`, not sure if we want it. |
| Comment by Masaki Fujimoto [ 20/Jan/13 ] |
|
I have just one code table. PK is a combination of CLASS and CODE columns. I use CLASS column as discriminator, and CODE column is ID of each inheritance. value in CODE column won't be unique by itself in the table but I thought SINGLE_TABLE inheritance can cover that. If this structure is unconventional, I'll have to look for workaround. thanks for all your help |