更新元素的 Doctrine2 缓存

Posted

技术标签:

【中文标题】更新元素的 Doctrine2 缓存【英文标题】:Doctrine2 Caching of updated Elements 【发布时间】:2012-05-15 16:55:33 【问题描述】:

我对教义有疑问。我喜欢缓存,但如果我更新一个实体并刷新,难道不应该学说 2 能够清除它的缓存吗? 否则缓存对我来说用处不大,因为这个项目有很多交互,我总是不得不为每个查询禁用缓存。 如果缓存总是向他们显示旧的缓存版本,用户将看不到他们的交互。

有办法解决吗?

【问题讨论】:

您只想完全关闭缓存吗?我知道您可以使用 $deleted = $cacheDriver->deleteAll(); 清除缓存 @Gohn67:我如何获得 CacheDriver? 【参考方案1】:

您是在谈论在同一运行时(请求)中保存和获取新实体吗?如果是这样,那么您需要刷新实体。

$entity = new Entity();
$em->persist($entity);
$em->flush();
$em->refresh($entity);

如果实体是托管的并且您进行了更改,这些将应用于实体对象,但仅在调用 $em->flush() 时持久化到您的数据库。

如果您的缓存正在为新请求返回旧数据集(尽管它已在数据库中成功更新),那么听起来您发现了一个错误。你可以在这里提交>>http://www.doctrine-project.org/jira/secure/Dashboard.jspa

【讨论】:

我确实试过了。我加载实体,进行更改,持久化它,刷新它,刷新它。还是一样。但也许那是因为我刷新了实体而不是它的所有相关对象,所以相关对象仍然来自缓存? 当您说“加载”实体时,您的意思是创建它还是从数据库中获取它?如果它被获取,那么它处于“托管”状态,您不需要对其使用 persist() 方法。刷新托管实体也可以删除您对其所做的任何修改。如果它是新的:创建 -> 持久 -> 刷新 -> 刷新。如果它是托管的(从数据库中获取):获取 ->(进行更改)-> 刷新。 我也试过了,刷新并不能真正帮助“对抗”缓存。它的工作原理如下: $entity = $service->loadCached();回声 $entity->getData(); //返回缓存的数据 $em->refresh();回声 $entity->getData(); //返回未缓存的数据听起来不错,但不会使实际缓存无效,因此在下次运行 loadCached() 时,您仍将获得旧数据。看起来没有别的办法,只能像 Gohn67 建议的那样手动清除缓存。【参考方案2】:

Doctrine2 从来没有 deleteByPrefix 之类的删除方法,该方法在某个时间点(3 年前)存在于 Doctrine1 中,但由于造成更多麻烦而被删除。

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html#deleting 页面已过时(下一个版本的教义2 文档将删除这些方法)。你现在唯一能做的就是手动管理缓存:找到 id 并在每次更新后手动删除它。

更高级的学说缓存是 WIP:https://github.com/doctrine/doctrine2/pull/580。

【讨论】:

是的,老票,我还是很好奇。我正在调查“deleteByPrefix”,但找不到任何关于它的信息。它遇到了什么样的问题?性能问题?也许我应该就此提出一个新问题。【参考方案3】:

这是根据关于如何清除缓存的 Doctrine2 文档。我什至不确定这是否是您想要的,但我想这是可以尝试的。

Doctrine2 的缓存驱动程序有不同级别的删除缓存条目。

您可以通过直接 id、使用正则表达式、后缀、前缀和普通删除缓存中的所有值来删除

所以要删除你所做的一切:

$deleted = $cacheDriver->deleteAll();

要按前缀删除,你会这样做:

$deleted = $cacheDriver->deleteByPrefix('users_');

我不确定 Doctrine2 是如何命名他们的缓存 id 的,所以你必须挖掘它。

删除缓存的信息在这里:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html#deleting

要获取缓存驱动程序,您可以执行以下操作。它没有在文档中描述,所以我只是稍微跟踪了一下代码。

我假设您在此示例中有一个实体管理器实例:

$config = $em->getConfiguration(); //Get an instance of the configuration
$queryCacheDriver = $config->getQueryCacheImpl(); //Gets Query Cache Driver
$metadataCacheDriver = $config->getMetadataCacheImpl(); //You probably don't need this one unless the schema changed

或者,我想您可以将 cacheDriver 实例保存在某种注册表类中并以这种方式检索它。但取决于你的喜好。就我个人而言,我尽量不要过多地依赖注册表。

您可以做的另一件事是告诉您正在执行的查询不要使用结果缓存。再说一次,我认为这不是你想要的,只是把它扔在那里。主要是您似乎还不如完全关闭查询缓存。那是除非它只是一些您不想使用缓存的特定查询。

此示例来自文档:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html#result-cache

$query = $em->createQuery('select u from \Entities\User u');
$query->useResultCache(false); //Don't use query cache on this query
$results = $query->getResult();

【讨论】:

我想知道,他们是否删除了 v.2.2.2 上的“deleteByPrefix()”?我对学说来源进行了全面搜索,但找不到这些方法 deleteByPrefix 不适用于内存缓存驱动程序。

以上是关于更新元素的 Doctrine2 缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ZendOpCache 用于 Doctrine2 缓存?

如何在 symfony 中更新新版本的 Doctrine2 和 ORM?

Symfony2 / Doctrine2:不要在模式上删除全文索引:更新

如何使用Doctrine2将实体的克隆保存为更新

Doctrine2更新导致Zend Framework 3中的AnnotationRegistry registerLoader错误

Doctrine2重复键名错误