我正在使用Doctrine 2作为我的ORM,事情进展顺利,但我一直在想EntityManager#persist()
方法。 "Persisting entities"文档说明了对persist()
对象X
的调用:
如果X是预先存在的管理实体,则持久化操作会忽略它。
这让我相信只有当对象是新的并且尚未保存到数据库时才需要调用persist()
。但是,"Deferred Explicit" change tracking policy的文档说:
必须在对象上调用... Doctrine 2仅考虑通过调用EntityManager#persist(entity)...明确标记用于更改检测的实体...
...听起来像persist()
才能更新它。应该何时调用persist()
?如果仅在新对象上,无论何时更新实体并让Doctrine解决差异,是否存在重要性能来调用它?
答案 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
(这些是两个政策中行为不同的唯一地方)。