教义 resultCache 打破了实体删除

Posted

技术标签:

【中文标题】教义 resultCache 打破了实体删除【英文标题】:Doctrine resultCache breaks entity removal 【发布时间】:2013-08-07 07:32:24 【问题描述】:

我在使用 Doctrine ORM 的结果缓存时遇到了问题。该应用程序通过 JSON REST 接口管理创建/删除通道实体并将数据添加到通道以进行监控。出于性能原因,需要跨请求缓存通道实体,因为它们大多是静态的。

在单元测试期间,我们发现流程存在问题 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 如何影响实体的删除,尤其是当通道实体更新时会清除结果缓存?

更新

在从现有实体管理器中添加新检索到的实体上的数据后检查通道实体状态,它的状态已经 DETACHED。这也是结果缓存第一次发挥作用。

结果缓存如何/为什么使实体分离?

【问题讨论】:

【参考方案1】:

通过 Doctrine 找到答案:http://www.doctrine-project.org/jira/browse/DDC-446 缓存的实体总是“分离的”。如果您需要一个托管实体,您可以合并它——尽管需要额外的数据库查询。

结论

如果需要删除托管实体等,最好不要使用缓存的查询结果。

更新

此行为在 Doctrine 2.3 中已更改 - 缓存的结果现在始终是水合的,因此可以管理。

【讨论】:

以上是关于教义 resultCache 打破了实体删除的主要内容,如果未能解决你的问题,请参考以下文章

教义实体映射不正确

教义:通过关系发现了一个新实体...尝试刷新时

教义事件,更新持久化实体

具有连接的实体和存储库中的教义可重用标准

两个实体之间的教义关系

教义自定义存储库方法和非托管实体