我正在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)。