addiks / doctrine2_tweaks
为 doctrine2 项目提供一些组件替换,带有调整和修改后的行为。
Requires
- php: >=8.0.0
- doctrine/annotations: *
- doctrine/orm: *
- symfony/cache: *
Requires (Dev)
- phpunit/phpunit: ^9.5
README
此存储库代表了一组替代组件的集合,这些组件对 doctrine2 项目进行了调整和/或行为更改。
UnitOfWork 保存状态
Addiks\DoctrineTweaks\UnitOfWork\UnitOfWorkSaveState
这代表了一个 doctrine 单个工作单元实例的保存状态。使用它,您可以始终将单个工作单元实例的状态回滚到先前状态。
这对于批量操作非常有用:在批量处理开始时创建一个保存状态,然后在每次刷新后恢复它。这样,单个工作单元将永远不会包含已经刷新的对象,从而节省内存和(执行)时间。
这与简单的实体管理器 clear
调用不同,因为它保留了在保存状态创建时存在于单个工作单元中的所有对象。保留这些对象可以帮助(并且通常确实会)保持单个工作单元状态与应用程序其余部分的连贯性。
记得在恢复时也调用 "gc_collect_cycles()" 来实际释放内存。
示例
<?php use Addiks\DoctrineTweaks\UnitOfWork\UnitOfWorkSaveState; $saveState = new UnitOfWorkSaveState($entityManager->getUnitOfWork()); foreach ($thingsToImport as $counter => $thing) { $importer->import($thing); # Import a thing, add it to a collection or something if ($counter % 100 === 0) { $entityManager->flush(); # Send new entities to database $saveState->restore(); # Remove imported entities from unit-of-work gc_collect_cycles(); # Clean up memory } }
事务性实体管理器
Addiks\DoctrineTweaks\TransactionalEntityManager (Doctrine 的替代方案 Doctrine\ORM\EntityManager)
通过 ORM 管理持久化实体。
此实体管理器提供了 doctrine 自己的实体管理器的替代方案。与 doctrine 的实体管理器相比,此实体管理器永远不会关闭。相反,在回滚时,它会将所有管理的实体的一部分回滚到事务创建时的点。
它通过管理不仅一个 UnitOfWork,而是一系列 UnitOfWork 实例来实现。每个打开的事务以及根 UnitOfWork 都有一个 UnitOfWork。这个堆栈中的每个 UnitOfWork 都包含从下一个事务开始时管理的实体状态。堆栈顶部的 UnitOfWork 总是当前正在使用的。当事务开始时,最顶部的 UnitOfWork 被克隆,并将其克隆放置在堆栈顶部成为新的当前 UnitOfWork。
当事务提交时,堆栈的第二顶部的 UnitOfWork 被移除,并用当前和顶部的 UnitOfWork 替换。还有一个名为 "commitAndDetachNewEntities" 的替代提交方法,该方法还会断开所有在事务开始时未知的事实体,这在批量处理中的每次迭代中可能是什么你想要做的,以防止管理大量实体。
当事务回滚时,最顶部的 UnitOfWork 被丢弃,其前一个 UnitOfWork(仍包含事务开始时实体的状态)成为新的顶部和当前的一个。
还有一个用于回滚事务的替代方法 "rollbackEntities",它使用在事务开始时仍包含管理实体状态的那个 UnitOfWork 来回滚所有管理实体的状态(这将导致昂贵的回滚!)
上述段落中描述的过程允许使用事务实现有意义的流程。如果过程失败并触发回滚,不仅数据库中的状态会被回滚,所有管理实体的状态也会被回滚。这使得可以重新尝试执行失败的过程,或者使用相同的实体管理器继续执行下一个过程。这之所以可行,是因为运行时的状态是已知的,它与事务开始时相同。这遵循了“回滚”的含义 => 从错误状态回到已知状态。如果正确使用,这个实体管理器可以减轻那些对事务非常关注的开发者的大烦恼。
请注意,该组件目前仅进行了粗略测试,应更多视为一个概念验证。如果您真的决定在生产环境中使用它,请先进行彻底测试,并查找对性能可能产生的影响。如果您实际上在任何地方使用了它,或者更好的是,将其分支并改进它,请提供反馈。