知道何时呼叫坚持

时间:2011-08-31 20:24:52

标签: php doctrine-orm

我正在使用Doctrine 2作为我的ORM,事情进展顺利,但我一直在想EntityManager#persist()方法。 "Persisting entities"文档说明了对persist()对象X的调用:

  

如果X是预先存在的管理实体,则持久化操作会忽略它。

这让我相信只有当对象是新的并且尚未保存到数据库时才需要调用persist()。但是,"Deferred Explicit" change tracking policy的文档说:

  

... Doctrine 2仅考虑通过调用EntityManager#persist(entity)...明确标记用于更改检测的实体...

必须在对象上调用

...听起来像persist()才能更新它。应该何时调用persist()?如果仅在新对象上,无论何时更新实体并让Doctrine解决差异,是否存在重要性能来调用它?

2 个答案:

答案 0 :(得分:11)

使用Deferred Explicit policy(它不是默认策略),您需要在每个已修改的实体上显式调用persist()以使其继承。 (级联持久性关联除外。)

Doctrine仍然需要将每个属性的新值与原始值进行比较,以了解要更新的属性,因此如果persist()实体过多,则可能会影响性能。

使用default change tracking policy,您只需要对尚未由Doctrine管理的实体(使用new创建的实体)调用persist。使用此策略,当您调用flush()时,doctrine会自动检测哪些实体已更新并需要保留。

答案 1 :(得分:6)

文档有些误导。在隐式跟踪模式中,所有实体都具有状态(托管,删除,分离等);通过find()获得的实体和类似的方法(基本上所有不是用new创建的)都已处于托管状态。在flush()上,检查所有托管(和删除)的entites是否有更改,并在必要时在DB中更新。

在显式跟踪模式下,还有一个额外的脏检查列表,persist()将对象(以及可能关联的对象,具体取决于级联设置)添加到该列表中。仅考虑脏检查列表中的项目进行更新。刷新后清除脏检查列表,因此如果再次刷新并再次更改同一对象,则必须再次调用persist()。 (相反,管理状态在刷新后保留。)

您可以在Doctrine\ORM\UnitOfWork课程中查看自己的详细信息;搜索isChangeTrackingDeferredImplicit / isChangeTrackingDeferredExplicit(这些是两个政策中行为不同的唯一地方)。

相关问题