我正在一个在Symfony 2中使用Doctrine 2的项目中工作,我使用MEMCACHE来存储学说的结果。 我对从MEMCACHE检索的对象有问题。
我发现此帖子类似,但这种方法无法解决我的问题:Doctrine detaching, caching, and merging
这是方案
/**
* 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进行了更新,并更新了更新的列。真正的问题是它为每个条目进行更新查询,我只想添加对实体的引用。 我怎么能成功呢? 任何帮助将不胜感激。
答案 0 :(得分:2)
<强>为什么强>
当实体合并回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();
该引用将是一个代理(除非它已经托管),并且根本不会从db加载(甚至在刷新EntityManager时也是如此)。 / p>
结果缓存
您可以使用Doctrine的result cache来代替使用自己的缓存机制。它会缓存查询结果,以防止访问数据库,但(如果我没有弄错的话)仍会保留这些结果。这可以防止缓存实体本身可能遇到的许多问题。
答案 1 :(得分:0)
您想要实现的目标称为部分更新。 你应该使用这样的东西
/**
* 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上的PATCH(或PUT)。