php - 学说 2 和 ORM : how to cache every query for some entity?

标签 php caching orm doctrine-orm

我与这个问题斗争了很多时间,发现正式地,我只能缓存一些自定义查询(查询对象上的 useResultCache(true))。但是我需要将应用程序中的每个查询缓存到某个表中。 EntityManager 上的 find* 方法怎么样?...

有人可以帮我找到一个优雅的解决方案吗?

最佳答案

这还不受支持,您最终应该在服务层或扩展存储库中处理它。

您正在寻找的是 second level cache as in Hibernate ,它基本上允许您插入一个键值存储,如 redis、riak、mongodb 等,以便在操作是简单的获取操作时使事情变得非常快。

https://github.com/doctrine/doctrine2/pull/580 有一个正在进行的拉取请求,它可能会出现在 Doctrine ORM 2.5 中,所以请回顾一下。

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Cache\ArrayCache;

class MyBaseRepo extends EntityRepository
{
    public function __construct(EntityManager $entityManager)
    {
        parent::__construct($entityManager);
        $cache       = $em->getConfiguration()->getHydrationCache();
        $this->cache = $cache ?: new ArrayCache();
    }

    public function find($id)
    {
        if (!$object = $this->tryFetchFromCache($id)) {
            $object = parent::find($id);
            $this->cache->save($this->generateKey($id), $object);
        }

        return $object;
    }

    protected function tryFetchFromCache($id)
    {
        if (!$object = $this->cache->fetch($this->generateCacheKey($id))) {
            return null;
        }

        return $this->getEntityManager()->merge($object);
    }

    public function generateCacheKey($id) { /* ... */ }
}

您可以在引导您的应用程序时强制将其作为配置中 ORM 的基础存储库:

$configuration = new \Doctrine\ORM\Configuration();

$configuration->setDefaultRepositoryClassName('My\MyBaseRepo');

当您的任何实体发生更新/保存时,这也会强制您清除缓存条目:

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;

class IssueUpdateSubscriber implements EventSubscriber
{
    public function onFlush(OnFlushEventArgs $args)
    {
        $em  = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        if (!$cache = $em->getConfiguration()->getHydrationCache()) {
            return;
        }

        $busted = array_merge(
            $uow->getScheduledEntityUpdates(),
            $uow->getScheduledEntityDeletions(),
        );

        foreach ($busted as $entityToClear) {
            $className  = get_class($entityToClear);
            $metadata   = $em->getClassMetadata($className);
            $repository = $em->getRepository($className);
            $id         = $metadata->getIdentifierValues($entityToClear);

            $cache->delete($repository->generateCacheKey($id));
        }
    }

    public function getSubscribedEvents()
    {
        return array(Events::onFlush);
    }
}

请注意,此实现不会拦截给定实体对数据库的所有访问。它不会拦截由代理引起的延迟加载初始化,它非常脆弱,所以请设置一些适当的集成测试来支持它。

关于php - 学说 2 和 ORM : how to cache every query for some entity?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15661296/

相关文章:

orm - 一旦模型定义,如何建立 bookshelf.js 关系?

php - 注销代码点火器

带有while循环的php多个curl url

php - 尝试在 PHP 中进行复杂的搜索

php - 缩短字符串 PHP

c# - 静态成员变量是否可以用于缓存静态类中的值?

java - Spring Cache 刷新过时的值

PHP ORMs : Doctrine vs. 推进

java - 以编程方式清除 Java\CPU 缓存

Django 1.4 预取相关不保留继承模型的结果