Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getReference() of doctrine Entity Manager

Situation:

I want to use the getReference() function of doctrine2 Entity Manager. However, in a situation where I ask for an object that has been deleted from the database, I obtain a proxy if I ask for that same object more than once.

An example:

//A random article object...that has been deleted from the database
$articleClass = 'Acme\ArticleBundle\Entity\Article';
$articleIdentifiers = array('id'=>1);
$i = 0;

//We ask for its reference twice
do{
    try {
        echo "a";
        $subject = $this->em->getReference(
            $subjectClass,
            $subjectIdentifiers
        );
       //call this object now
       var_dump($subject);

    } catch (\Exception $e) {
        echo "b";
    }
    $i++;
} while ($i <2);

The output:

a
b
a
object(Proxies\__CG__\Acme\ArticleBundle\Entity\Article)

How can I get a proxy for an object that doesn't even exist in the database? If I comment this line, the entityManager does not manage the object and I obtain the output abab, which to me makes more sense as I don't want to get a proxy object that does not exist in the database. For info, the proxy object returned has all its properties null. I therefore obtain a proxy for an object that does not exist in the database. So, if I ask for this object I get a "Not found Entity" exception.

The challenge

Can anyone make any sense of this? Is there a way to rely on getReference() to tell us whether this object really does exist in the database?

like image 759
Mick Avatar asked May 09 '13 06:05

Mick


People also ask

What is the difference between methods find vs getReference?

The find method always returns an entity object. Hibernate initializes its attributes based on the defined FetchTypes. If you're using a default mapping, Hibernate fetches all basic attributes and initializes all to-one associations. The getReference method returns a reference to an entity object.

What are Doctrine proxies?

A Doctrine proxy is just a wrapper that extends an entity class to provide Lazy Loading for it. By default, when you ask the Entity Manager for an entity that is associated with another entity, the associated entity won't be loaded from the database, but wrapped into a proxy object.

How Doctrine works?

Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an object from the database, Doctrine will keep a reference to this object inside its UnitOfWork. The array holding all the entity references is two-levels deep and has the keys root entity name and id.

What is a repository Doctrine?

A repository mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. In Doctrine, a repository is a class that concentrates code responsible for querying and filtering your documents.


2 Answers

There is no way to make getReference() check the database for the existence of the referenced object.

Actually, this is what getReference() and the proxies returned by it are all about: Creating placeholder objects (proxies) without going to the database. And you would rarely want to do that explicitly. Normally Doctrine does this internally when hydrating entities to create lazy loading placeholders for related entities based on foreign key values.

Why don't you just call find() on the Entity Manager? Are you aware that the EM will not query the DB more than once for the same object as long as you look it up by ID? Doctrine keeps track of already hydrated objects in the Unit Of Work and returns references to the existing objects in subsequent find() calls.

like image 192
literal Avatar answered Nov 01 '22 13:11

literal


If you use getReference to get an object, but then call a method on it such as getName then Doctrine will fetch the entity from the DB. It has no other way to find out the property (getName).


Concerning your challenge:

EntityManager->contains($entity) would be the preferred way to check if the entity from doctrine is in the entity manager

like image 41
Andrew Atkinson Avatar answered Nov 01 '22 12:11

Andrew Atkinson