Doctrine merge:DateTime字段始终更新

时间:2016-02-24 13:36:53

标签: php mysql symfony doctrine-orm doctrine

我创建了一个现有Id的新实体,我想更新相关的数据库记录。

学说merge 是我最好的朋友:识别是否有更改并生成正确的更新查询。

$entity = new Entity();
$entity->setId(1);
$entity->setName('test');
$EntityManager->merge($entity);
$EntityManager->flush();

假设db中已存在id = 1的元素:如果名称与'test'不同,则Doctrine会生成此查询:

UPDATE table SET name = ? WHERE id = ? ["test","1"]

如果我再次运行上面的代码,Doctrine会识别出没有任何更改,也没有提交任何查询。

但是...... 当我设置DateTime字段时,Doctrine认为它已更改并始终运行更新查询:

$entity = new Entity();
$entity->setId(1);
$entity->setDate(new \DateTime(2000-01-01));
$EntityManager->merge($entity);
$EntityManager->flush();
//* ALWAYS commits this query:
>> UPDATE table SET date = ? WHERE id = ? ["2000-01-01 00:00:00","1"]

你知道一种避免这种无用更新的方法吗?谢谢!

2 个答案:

答案 0 :(得分:7)

正如@Raymond所说,这是预期的行为。

很遗憾,但如果您的合并不依赖date属性,则解决方法可能是在合并后设置日期,如下所示:

$entity = new Entity();
$entity->setId(1);
// Set all fields that the merge is depending on
// ...
$EntityManager->merge($entity);

$entity->setDate(new \DateTime('2000-01-01'));
$EntityManager->flush();

<强>更新

尝试之后,唯一的选择似乎是检索合并对象并通过再次刷新EntityManager来更新它。

您可以使用:

$entity = new Entity();
$entity->setId(1);
// Set all fields that the merge is depending on
$EntityManager->merge($entity);
$EntityManager->flush();

$entity = $EntityManager->getRepository('Your\Entity')->find(1); // Retrieve the entity
$entity->setDate(new \DateTime('2000-01-01'));
$EntityManager->flush(); // Reflush

<强> UPDATE2

我发现在合并后实现更新的更清洁的方式是重新合并实体,例如:

$entity = new Entity();
$entity->setId(1);
// Set all fields that the merge is depending on
$EntityManager->merge($entity); // The real merge that retrieve (without commit) or create
$EntityManager->flush();

$entity->setDate(new \DateTime('2000-01-01'));
$entityManager->merge($entity); // Remerge the object with the changed field
$EntityManager->flush(); // Working re-flush

但这并没有改变主要问题并且没有意义,因为你无法自己比较DateTime对象,$entity->getDate()在调用{{1}之前返回null即使在第一次合并之后也是如此。

Doctrine通过引用(哈希)将对象与setDate进行比较,即使对象日期未更改,===的新实例也会导致更新。

这是一个真正有问题的问题,可以通过使用\DateTime作为比较运算符来修复,但是教条不能在不打破其通用对象比较机制的情况下为==创建特定条件,涉及降低最常用功能之一的性能。

答案 1 :(得分:6)

显然,它似乎是Doctrine中的一个仍未解决的错误(参考Github

  

这是预期的行为,通过引用比较对象