Doctrine2 ORM 不会刷新在脚本之外更改的对象

问题描述 投票:0回答:2

我真的不知道如何给这个标题或搜索一个已经发布的问题,所以如果以前在这里见过这个问题,我很抱歉。

我使用以下代码得到了一些不需要的结果:

// 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());

    }

}

您可以看到,在第一个

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()
方法时,我实际上是从数据库中提取更新的数据。非常感谢任何帮助。

php symfony doctrine-orm
2个回答
30
投票

这确实是由用户ChocoDeveloper提供的。使用实体管理器上的

refresh($entity)
方法解决了我的问题。

例如:

$em->refresh($entity);

0
投票

对于那些没有通过接受的答案解决问题的人,还有另一种方法可以实现这一目标。

// Run either of the following lines
$em->clear();
$em->detach($model);
// Fetch the model again here.

如果您使用查询生成器来修改由实体管理器管理的对象,您可能需要这样做。请注意,

clear
方法将使所有托管对象分离,而
detach
方法只会对传递的实体执行此操作,如本例所示。

// Save the model
$model = new Calendar();
$model->setTitle('Initial');
$repository->save($model);

$id = $model->getId();

$calendar = $repository->find($id);

var_dump($calendar->getTitle()); // "Initial"

/** @var EntityManagerInterface $em */
$em->createQueryBuilder();

// Update the calendar through query builder
$queryBuilder = $em->createQueryBuilder();
$queryBuilder
    ->update(Calendar::class, 'c')
    ->set('c.title', ':title')
    ->setParameter(':title', "Updated Title")
    ->andWhere(
        $queryBuilder->expr()->in('c.id', [$id])
    );

$queryBuilder->getQuery()->execute();

$em->detach($calendar);

var_dump($calendar->getTitle()); // "Initial"

$calendar = $repository->find($id); // Fetch again

var_dump($calendar->getTitle()); // "Updated Title"
© www.soinside.com 2019 - 2024. All rights reserved.