Php 原则2-如何在关系中使用从缓存检索的对象

Php 原则2-如何在关系中使用从缓存检索的对象,php,symfony,caching,doctrine-orm,doctrine,Php,Symfony,Caching,Doctrine Orm,Doctrine,我在一个项目中工作,在Symfony 2中使用了条令2,我使用MEMCACHE来存储条令的结果。 我对从MEMCACHE检索的对象有问题 我发现这篇文章很相似,但这种方法并不能解决我的问题: 情况就是这样 /** * This is in entity ContestRegistry * @var contest * * @ORM\ManyToOne(targetEntity="Contest", inversedBy="usersRegistered") * @ORM\JoinCo

我在一个项目中工作,在Symfony 2中使用了条令2,我使用MEMCACHE来存储条令的结果。 我对从MEMCACHE检索的对象有问题

我发现这篇文章很相似,但这种方法并不能解决我的问题:

情况就是这样

/**
 * This is in entity ContestRegistry
 * @var contest
 * 
 * @ORM\ManyToOne(targetEntity="Contest", inversedBy="usersRegistered")
 * @ORM\JoinColumn(name="contest_id", referencedColumnName="id", onDelete="CASCADE"))
 *
 */
protected $contest;
在其他实体中

 /**
 * @var usersRegistered
 * 
 * @ORM\OneToMany(targetEntity="ContestRegistry", mappedBy="contest")
 *
 */
protected $usersRegistered;
现在假设竞赛在缓存中,我想保存一个竞赛注册表项。 因此,我在缓存中检索对象竞赛,如下所示:

$contest = $cacheDriver->fetch($key);
$contest = $this->getEntityManager()->merge($contest);
return $contest;
就像我上次做的那样:

$contestRegistry = new ContestRegistry();
$contestRegistry->setContest($contest);
$this->entityManager->persist($contestRegistry);
$this->entityManager->flush();
我的问题是,条令正确地保存了新实体,但它也对实体竞赛进行了更新,并更新了更新的列。真正的问题是它对每个条目进行更新查询,我只想添加对实体的引用。 我怎样才能做到这一点? 任何帮助都将不胜感激。

为什么

当实体合并回EntityManager时,它将被标记为脏。这意味着在执行刷新时,将在数据库中更新实体。这对我来说似乎是合理的,因为当您管理一个实体时,实际上需要EntityManager来管理它;)

在您的情况下,您只需要该实体与另一个实体进行关联,因此实际上不需要对其进行管理。因此,我建议采取不同的办法

使用参考资料

因此,不要将
$contest
合并回EntityManager,而是获取对它的引用:

$contest    = $cacheDriver->fetch($key);
$contestRef = $em->getReference('Contest', $contest->getId());

$contestRegistry = new ContestRegistry();
$contestRegistry->setContest($contestRef);

$em->persist($contestRegistry);
$em->flush();
该引用将是一个代理(除非它已经被管理),并且根本不会从数据库加载(甚至在刷新EntityManager时也不会)

结果缓存


除了使用您自己的缓存机制之外,您还可以使用Doctrine的缓存机制。它缓存查询结果以防止访问数据库,但(如果我没有弄错的话)仍然会缓存这些结果。这就避免了缓存实体本身可能出现的许多问题。

您想要实现的是所谓的部分更新。 你应该用这样的东西来代替

/**
 * Partially updates an entity
 *
 * @param Object $entity The entity to update
 * @param Request $request
 */
protected function partialUpdate($entity, $request)
{
    $parameters = $request->request->all();

    $accessor = PropertyAccess::createPropertyAccessor();
    foreach ($parameters as $key => $parameter) {
        $accessor->setValue($entity, $key, $parameter);
    }
}
合并要求整个实体100%充满数据。 我还没有检查孩子们的行为(多对一、一对一等)关系


部分更新通常用于Rest API上的补丁(或PUT)。

您好,我尝试了两种解决方案,但第一种都不起作用。我不知道为什么。参考它的工作原理。也许当我更改跟踪策略时,我应该修改关系中涉及的所有实体?我已经研究过了,似乎不管更改跟踪策略如何,该实体都被标记为脏实体。所以这不是一个选择。我已经更新了我的答案。顺便说一句:我确实建议对所有实体使用延迟显式,因为刷新变得便宜得多。假设您加载了5000个实体并更改了1,延迟隐式将检查所有5000个,延迟显式将只检查您在上调用的1
$em->persist()