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

时间:2014-05-07 14:02:08

标签: php symfony caching doctrine-orm doctrine

我正在一个在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进行了更新,并更新了更新的列。真正的问题是它为每个条目进行更新查询,我只想添加对实体的引用。 我怎么能成功呢? 任何帮助将不胜感激。

2 个答案:

答案 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)。