2011-10-31 13 views
21

Deseo poder recuperar la versión existente de una entidad para poder compararla con la última versión. P.ej. Editando un archivo, quiero saber si el valor ha cambiado desde que estaba en el DB.¿Cómo detener Doctrine 2 desde el almacenamiento en caché de un resultado en Symfony 2?

$entityManager = $this->get('doctrine')->getEntityManager(); 
    $postManager = $this->get('synth_knowledge_share.manager'); 

    $repository = $entityManager->getRepository('KnowledgeShareBundle:Post'); 
    $post = $repository->findOneById(1); 

    var_dump($post->getTitle()); // This would output "My Title" 
    $post->setTitle("Unpersisted new title"); 

    $existingPost = $repository->findOneById(1); // Retrieve the old entity 

    var_dump($existingPost->getTitle()); // This would output "Unpersisted new title" instead of the expected "My Title" 

¿Alguien sabe cómo puedo evitar este caché?

Respuesta

40

Es un comportamiento normal.

Doctrine almacena una referencia de las entidades recuperadas en el EntityManager para que pueda devolver una entidad por su id sin realizar otra consulta.

Puede hacer algo como:

$entityManager = $this->get('doctrine')->getEntityManager(); 
$repository = $entityManager->getRepository('KnowledgeShareBundle:Post'); 
$post = $repository->find(1); 

$entityManager->detach($post); 

// as the previously loaded post was detached, it loads a new one 
$existingPost = $repository->find(1); 

Pero ser consciente de que a medida que la entidad $ post se separó, se debe utilizar el método -> merge() si quiere persistir nuevo.

+4

Delicioso, el 'detach' es perfecto. –

+10

Gracias por esto. Sugerencia rápida: si necesita separar todas las entidades (por ejemplo, en pruebas no aisladas), puede usar '$ entityManager-> clear()'. – richsage

+0

La otra cosa que debe observar aquí es si tiene o no abierta una transacción. Si ha realizado un '$ entityManager-> beginTransaction()', asegúrese de cerrar la transacción (por ejemplo, '$ entityManager-> rollback()') antes de intentar borrar el administrador de entidades. Una transacción abierta obligará a una vista coherente, por lo tanto no actualizada, de la base de datos. – stanhope

8

También puede usar el método refresh, que actualiza el estado persistente de una entidad desde la base de datos, anulando cualquier cambio local que aún no se haya conservado. Algo así como:

$entityManager = $this->get('doctrine')->getEntityManager(); 
$repository = $entityManager->getRepository('KnowledgeShareBundle:Post'); 
$post = $repository->find(1); 

$entityManager->refresh($post); 

ahora $ post contiene la última versión de la base de datos.

+1

¡Usted señor es un salvavidas! –

+0

esto es realmente útil y parece ser poco conocido. Vale la pena señalar que cascade = "REFRESH" en entidades relacionadas para que esto funcione bien – DevDonkey