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)
你知道一种避免这种无用更新的方法吗?谢谢!
正如@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如果不破坏它们的通用对象比较机制,则学说不能为特定条件做出决定,这涉及降低最常用特征之一的性能.
| 归档时间: |
|
| 查看次数: |
949 次 |
| 最近记录: |