Doctrine2 ORM 不会刷新在脚本之外更改的对象
我真的不知道如何命名或搜索已经发布的问题,如果之前在这里看到过,我很抱歉.
我使用以下代码得到了一些不想要的结果:
//获取对象管理器$fooManager = $this->getContainer()->get('foo_manager');$barManager = $this->getContainer()->get('bar_manager');//无限循环为了 (;;) {//继续获取未初始化的foo"对象,如果没有则退出while (($foo = $fooManager->findUninitialized()) !== null) {//一个未初始化的foo"需要创建一个bar"对象$bar = $barManager->create();$bar->setA('...');//将bar"保存到数据库中,update() 将执行一次flush()$barManager->更新($bar);//将bar"关联到foo"$foo->setBar($bar);//将foo"保存到数据库中,update() 将执行一次flush()$fooManager->update($foo);}//继续获取未处理的foo"对象,如果没有则退出while (($foo = $fooManager->findUnprocessed()) !== null) {//处理来自foo"对象的bar"的数据进程($foo->getBar()->getB());}}
您可以看到,在第一个 while
循环中,正在创建 $bar
对象并将其放入数据库.另一个脚本正在处理这些并对其进行处理.
在第二个 while
循环中,$foo
对象试图访问它们修改后的bar"对象(注意 getB()
被调用,我们可以假设在另一个单独执行的脚本中 setB()
用于改变对象的状态).
但是,在第二个循环中,当我调用 getB()
时,它不会返回我在其他脚本中使用 setB()
设置的值.>
我可以确保所有数据都被正确地持久化(并刷新)到数据库中,因此当在第二个循环中调用 getB()
时,保存B"的任何内容都已更改并且存在于数据库中.
我注意到的一件事是,在日志文件中,当我调用 $foo->getBar()
时,我没有看到为bar"提取数据的查询第二个循环(这些应该被延迟加载).此外,如果我 var_dump()
在第二个循环中从 $foo->getBar()
返回的值,它看起来与关联的bar"对象看起来完全一样在第一个循环结束时.
我认为有某种缓存或正在发生的事情(因为我在脚本执行的早期更改了那些bar"对象,Doctrine 似乎只是重新使用它们而不是重新加载它们的数据来自数据库).
我知道我正在尝试做的事情可能并不常见.我正在做的是使用 Symfony2 控制台命令功能编写一些命令行守护进程"来帮助处理一些数据;包含此代码的守护进程"正在与另一个守护进程"一起运行,该守护进程"处理创建的那些bar"对象.
好奇是否有办法在我调用 $foo->getBar()
方法时将这个问题修复到我的第二个循环中的位置,我实际上是从数据库.非常感谢任何帮助.
这确实是由用户 ChocoDeveloper 提供的.在实体管理器上使用 refresh($entity)
方法解决了我的问题.
例如:
$em->refresh($entity);
I really didn't know how to title this or search for an already posted question, so my apologies if this has been seen on here before.
I am getting some undesired results with the following code:
// get object managers
$fooManager = $this->getContainer()->get('foo_manager');
$barManager = $this->getContainer()->get('bar_manager');
// infinite loop
for (;;) {
// keep getting unitialized "foo" objects, or quit if none
while (($foo = $fooManager->findUninitialized()) !== null) {
// an uninitialized "foo" will need to make a "bar" object
$bar = $barManager->create();
$bar->setA('...');
// save "bar" to database, update() WILL perform a flush()
$barManager->update($bar);
// make the association of "bar" to "foo"
$foo->setBar($bar);
// save "foo" to database, update() WILL perform a flush()
$fooManager->update($foo);
}
// keep getting unprocessed "foo" objects, or quit if none
while (($foo = $fooManager->findUnprocessed()) !== null) {
// process the data from "foo" object's "bar"
process($foo->getBar()->getB());
}
}
You can see that in the first while
loop, $bar
objects are being made and put into the database. Another script is picking up on these and doing things to them.
In the second while
loop, the $foo
objects are trying to access their modified "bar" object (notice the getB()
being called, we can assume that in another script being executed separately setB()
was used to change the state of the object).
However, in the second loop, when I call getB()
, it is not returning the value I set with setB()
in that other script.
I can ensure all of the data is being properly persisted (and flushed) to the database, so when the getB()
is called in that second loop, whatever was holding "B" was changed and is present in the database.
One thing I've noticed is that in the log file, I am not seeing a query to pull in the data for "bar" when I call $foo->getBar()
in the second loop (these should be lazily loaded). Also, if I var_dump()
the value returned from $foo->getBar()
in the second loop, it looks exactly like the associated "bar" object would look by the end of the first loop.
I'm thinking that there is some kind of caching or something going on (since I've altered those "bar" objects earlier in the script execution, Doctrine seems like it is just re-using those rather than reloading their data from the database).
I know what I am trying to do is probably not common. What I am doing is using the Symfony2 console command features to write a few command-line "daemons" to help with processing some data; the "daemon" that contains this code is being run in conjunction with another "daemon" that processes those "bar" objects that get created.
Curious as to whether there is a way to fix this to where in my second loop when I call the $foo->getBar()
method, I am actually pulling the updated data from the database. Any help is greatly appreciated.
This was really provided by the user ChocoDeveloper. Making use of the refresh($entity)
method on the entity manager solved my problem.
For example:
$em->refresh($entity);
相关文章