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


Doctrine 2 - How to use objects retrieved from cache in relationships

我正在Symfony 2中使用Doctrine 2的项目中工作,我使用MEMCACHE来存储Doctrine的结果。我有一个问题,从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在缓存中,我想保存一个ContestRegistry条目。因此,我在缓存中检索对象竞赛,如下所示:

$contest = $cacheDriver->fetch($key);
$contest = $this->getEntityManager()->merge($contest);
return $contest;

作为我做的最后一个操作:

$contestRegistry = new ContestRegistry();
$contestRegistry->setContest($contest);
$this->entityManager->persist($contestRegistry);
$this->entityManager->flush();

我的问题是doctrine正确地保存了新实体,但它也对实体Contest进行了更新,并更新了已更新的列。真正的问题是它对每个条目进行更新查询,我只想添加对实体的引用。我怎样才能使它成为可能?

为什么

当一个实体被合并回EntityManager时,它将被标记为dirty。这意味着在执行刷新时,将在数据库中更新实体。这对我来说似乎是合理的,因为当你让一个实体管理时,你实际上希望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时也不会)。

<<p> 结果缓存/strong>

您可以使用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);
    }
}

Merge要求整个实体100%充满数据。我还没有检查与孩子(多对一,一对一,等等)关系的行为。

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