2013-08-07 1 views
0

У меня возникли проблемы с использованием кэша результатов Doctrine ORM. Приложение управляет созданием/удалением объектов канала и добавлением данных в каналы для целей мониторинга через интерфейс JSON REST. Кэширование объектов канала по запросам желательно по соображениям производительности, поскольку они в основном статичны.Doctrine resultCache прерывает удаление объекта

Во время модульного тестирования мы обнаружили проблемы с потоком 1) создаем канал 2) добавляем данные и 3) удаляем канал. Новый менеджер объект используется в коде ниже, чтобы моделировать отдельные запросы в формате JSON для целей тестирования:

public function run() { 
    // 1) add channel 
    $this->em = self::createEntityManager(); 
    $channel = new Model\Channel('power'); 
    echo($uuid = $channel->getUuid()); 

    $this->setProperties($channel, array('title'=>'Meter', 'resolution'=>100)); 

    $this->em->persist($channel); 
    $this->em->flush(); 
    $this->clearCache(); 

    // 2) add data 
    $this->em = self::createEntityManager(); 
    $channel = $this->get($uuid); 
    $this->dumpEntityState($channel, 'add '); 

    $channel->addData(new Model\Data($channel, 1000000, 1)); 
    $this->em->flush(); 
    $this->dumpEntityState($channel, 'adddata '); 

    // this fixes the problem 
    // $this->clearCache(); 

    // 3) delete channel 
    $this->em = self::createEntityManager(); 
    $entity = $this->get($uuid); 
    $this->dumpEntityState($channel, 'delete '); 

    if ($entity instanceof Model\Channel) { 
     $entity->clearData($this->em); 
    } 

    $this->em->remove($entity); 
    $this->em->flush(); 
    $this->clearCache(); 
} 

Субъект канал извлекается по идентификатору:

public function get($uuid) { 
    if (!Util\UUID::validate($uuid)) { 
     throw new \Exception('Invalid UUID: \'' . $uuid . '\''); 
    } 

    $dql = 'SELECT a, p 
     FROM Volkszaehler\Model\Entity a 
     LEFT JOIN a.properties p 
     WHERE a.uuid = :uuid'; 

    $q = $this->em->createQuery($dql); 
    $q->setParameter('uuid', $uuid); 

    // this breaks the app 
    $q->useResultCache(true); 

    try { 
     return $q->getSingleResult(); 
    } catch (\Doctrine\ORM\NoResultException $e) { 
     throw new \Exception('No entity found with UUID: \'' . $uuid . '\'', 404); 
    } 
} 

Теперь проблема заключается в том, что когда-то useResultCache(true) используются, удаление объекта на шаге 3) приводит к ошибке:

Uncaught exception 'InvalidArgumentException' with message 'A detached entity can not be removed.' in \ORM\UnitOfWork.php 

Как только useResultCache() является false, проблема ушла.

Как может resultCache влиять на удаление объектов, тем более, что кэш результатов очищается всякий раз, когда объект канала обновляется?

ОБНОВЛЕНИЕ

Проверка состояния сущности канала после добавления данных на свеж извлеченного объекта из существующего менеджера сущности, это состояние уже ОТДЕЛИЛО. Это также первый раз, когда кэш результатов вступает в игру.

How/why result cache делает объекты DETACHED?

ответ

0

Ответ найден с доктриной: http://www.doctrine-project.org/jira/browse/DDC-446 кэшированные объекты всегда «отстранены». Если вам нужен управляемый объект, вы можете объединить его, хотя и за счет дополнительного запроса БД.

Заключение

Если управляемые объекты необходимы для удаления и т.д., лучше не использовать кэшированные результаты запроса.

Update

Такое поведение было изменено в Учении 2.3- кэшированные результатов теперь всегда увлажненный и, следовательно, стать управляемым.

Смежные вопросы