禁用缓存并在不分离实体的情况下获取新数据



TL;DR:我正在寻找部分或完全禁用Doctrine缓存的方法

我试图从数据库中获取新的数据,首先我不知道Doctrine,它有某种缓存,它是如何工作的,它不会两次从数据库中提取数据。

(这可能比这更复杂,但我是如何理解它的,它是如何为我工作的,我来这里不是为了解释它是如何工作的,因为我对这种学说的机制有问题。)

例如,假设我有代码(我在Symfony下工作):

$em = $this->getDoctrine()->getManager();
$repo = $this-getRepository('AppBundle:User');
$user = $repo->getUserById(1);
echo $user->getName(); // It will print "User"
sleep(5); // I give myself some time to change user name to anything else than "User"
$sameUser = $repo->getUserById(1);
echo $sameUser->getName(); // It still prints out "User"

现在,为了解决这个问题,我不得不使用$em->detach($user),并且只有在那之后,$sameUser才包含从数据库中提取的fersh数据。我曾希望在useResultCache

useQueryCache但假设我有引用其实例之一的实体A,因此例如userAserBby Referer字段的字段。

当我分离userB以从数据库而不是缓存中新获取它时,我会得到我想要的,但如果我会在分离userB尝试保存userA,则Doctrine会抱怨它无法级联用户BserA的引用者是新实体(事实上它是分离的userB),为了让它再次工作,我必须将其设置为后退,例如:

$userA = $repo->getUserById(1);
$userB = $userA->getReferrer();
$em->detach($userB);
$userBAgain = $repo->getUserById($userB->getId());
$userA->setRferrer($userBAgain); //Without this doctrine thinks that userA has new entity that haven't been persisted yet.
$em->flush();    

好的,所以我有解决方法,一切都很好,但有什么我可以做的吗,这样我就可以在不使用分离或刷新实体的情况下获得相同的结果?我之所以这么问,是因为我一直发现自己陷入了我没有预料到的陷阱。这种陷阱的例子是:

$admin = $this->getUser(); //is current logged user
// it always exists there even if I don't use **getUser** method.
// This currently logged user is an admin, and it is Referrer of $user
$user = $payment->getUser(); //User, currently logged admin is referrer.
$em->detach($user); // Detached
$user = $repo->getUserById($user->getId()); //Fetch fresh data.
$payment->setUser($user); // Set it back so...
$em->flush() // ...So Doctrine won't complain about it when you save payment.

现在它看起来可能很容易,但我没有预料到,当我分离出我碰巧是其推荐人的某个支付的用户时,它也分离出了当前登录的用户($admin),当我刷新时,它试图保存$Sadminand$payment,但$admin实例引用了已分离的$user实例,它认为这是要持久化的新实例。解决此问题的一种方法是分离当前登录的用户,或者将$user设置回$sadmin,就像我对$Spayment所做的那样。

您可以使用$entityManager->refresh($entity)更新单个实体

刷新数据库中实体的持久状态,覆盖任何尚未持久化的本地更改。

或在DQL查询中使用查询::HINT_REFRESH:

public function getUserById()
{
return $this->em->createQuery('SELECT u, g FROM MyBundle:User u LEFT JOIN u.groups g WHERE u.id = 3')
->setHint(Query::HINT_REFRESH, true)
->getResult();
}

相关内容

  • 没有找到相关文章

最新更新