Doctrine merge:DateTime字段始终更新

T30*_*T30 13 php mysql doctrine symfony doctrine-orm

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

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

$entity = new Entity();
$entity->setId(1);
$entity->setName('test');
$EntityManager->merge($entity);
$EntityManager->flush();
Run Code Online (Sandbox Code Playgroud)

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

UPDATE table SET name = ? WHERE id = ? ["test","1"]
Run Code Online (Sandbox Code Playgroud)

如果我再次运行上面的代码,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"]
Run Code Online (Sandbox Code Playgroud)

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

cha*_*asr 8

正如@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();
Run Code Online (Sandbox Code Playgroud)

更新

尝试后,唯一的替代方案似乎是检索合并的对象并通过再次刷新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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

但这并没有改变主要问题并且没有真正意义,因为你不能自己比较DateTime对象,$entity->getDate()在调用之前返回总是null setDate,即使在第一次合并之后也是如此.

Doctrine通过引用(hash)比较对象,即使对象日期不变===,也会\DateTime导致更新的新实例.

这是一个真正有问题的问题,可以通过使用==作为比较运算符来解决,但是\DateTime如果不破坏它们的通用对象比较机制,则学说不能为特定条件做出决定,这涉及降低最常用特征之一的性能.


Ray*_*d A 7

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

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

  • 典型的程序员方法:_如果你无法解决bug,请将其标记为功能!_;) (12认同)
  • 有时我确实在教义中有了它。每当我遇到错误或问题时,官方的回应似乎是“解决此问题将破坏我们宝贵的精心编写的代码,因此我们将不对其进行任何处理并将其标记为预期的行为”。我真的很想知道这些人是否曾经在现实世界中从事过软件项目。 (2认同)