steevanb / doctrine-read-only-hydrator
仅用于读取的快速数据填充
Requires
- php: ^5.4.6 || ^7.0 || ^8.0
- doctrine/orm: ^2.4.8
Suggests
- steevanb/doctrine-stats: Add Doctrine stats : hydration time, lazy loaded entities, managed entities etc.
README
doctrine-read-only-hydrator
当你使用 Doctrine 检索数据时,你可以得到一个包含值的数组,或者一个完全填充的对象。
数据填充是一个非常缓慢的过程,它会在多个填充具有相同实体时返回相同的实体实例。当你想要插入/更新/删除实体时,这是可以的。但当你只想检索数据而不编辑它(例如显示列表)时,它会非常慢。
如果你想真正从数据库中检索数据,而不获取 UnitOfWork 引用:使用 Doctrine 数据填充你无法做到。每次查询都不会使用查询结果中的数据填充一个新的实体,而是返回由 UnitOfWork 知道的第一个填充的实体。
所以,如果你不需要修改你的实体,你想要真正更快,或者只是检索数据库中存储的数据,你可以使用 SimpleObjectHydrator 或 ReadOnlyHydrator。
这些填充的实体不能被持久化/刷新,因为它们没有在 UnitOfwork 中注册以提高性能。
不会进行延迟加载:为了更快,并且因为大多数时候,你必须创建一个完整的 QueryBuilder,它返回你所需的所有内容。
基准测试
此表显示了简单的基准测试结果(时间和 memory_get_peak_usage()),从 MySQL 5.7 数据库中检索了 30、1000 和 5000 个实体,使用 PHP 5.6.23 和 Doctrine 2.5.4。
当调用 $query->getArrayResult() 时使用 ArrayHydrator,当调用 $query->getResult()、$repository->findAll() 或 $repository->findBy() 时使用 ObjectHydrator。
SimpleObjectHydrator 和 ReadOnlyHydrator 由本库提供,请参阅上面的示例。
正如预期的那样,getArrayResult() 是检索数据最快的方式。但是,你必须与数组一起工作,因此你不能使用实体方法。
ReadOnlyHydrator 比 Doctrine ObjectHydrator 快 4 倍,但比 ArrayHydrator(难以使用)慢 40%。
如果你想要尽可能快,但又想得到实体结果而不是数组,SimpleObjectHydrator 看起来相当不错。
SimpleObjectHydrator
使用 QueryBuilder 中选择的所有字段填充你的实体。如果你尝试访问未加载的属性,不会抛出异常,你可以调用所有访问器。
- 不会执行延迟加载。
- 你不能持久化或刷新此实体。
- 当你想要比 Doctrine ObjectHydrator 快,但又不想插入/更新此实体,并且不保证可以访问未加载的属性时,非常有用。
- ReadOnlyHydrator
填充你的实体的代理,如果你尝试访问未通过 QueryBuilder 加载的属性,将抛出异常。
- 当你想要比 Doctrine ObjectHydrator 快,你不想插入/更新此实体,并且“确定”任何对未加载属性的访问都将抛出异常时,非常有用。
- 你不能持久化或刷新此实体。
- 当你想要比 Doctrine ObjectHydrator 快,但又不想插入/更新此实体,并且不保证可以访问未加载的属性时,非常有用。
- 示例
安装
# Foo\Repository\BarRepository use steevanb\DoctrineReadOnlyHydrator\Hydrator\ReadOnlyHydrator; class BarRepository { public function getReadOnlyUser($id) { return $this ->createQueryBuilder('user') ->select('user', 'PARTIAL comments.{id, comment}') ->join('user.comments', 'comments') ->where('user.id = :id') ->setParameter('id', $id) ->getQuery() ->getResult(ReadOnlyHydrator::HYDRATOR_NAME); } }
安装
composer require steevanb/doctrine-read-only-hydrator ^2.3
Symfony 2.x 或 3.x 集成
# app/AppKernel.php class AppKernel extends Kernel { public function registerBundles() { $bundles = [ new steevanb\DoctrineReadOnlyHydrator\Bridge\ReadOnlyHydratorBundle\ReadOnlyHydratorBundle() ]; } }
Symfony 4.x 或 5.x 集成
# config/bundles.php return [ steevanb\DoctrineReadOnlyHydrator\Bridge\ReadOnlyHydratorBundle\ReadOnlyHydratorBundle::class => ['all' => true], ];
手动集成
您需要将 SimpleObjectHydrator
和 ReadOnlyHydrator
注册到 Doctrine\ORM\Configuration
use steevanb\DoctrineReadOnlyHydrator\Hydrator\SimpleObjectHydrator; use steevanb\DoctrineReadOnlyHydrator\Hydrator\ReadOnlyHydrator; $configuration->addCustomHydrationMode(SimpleObjectHydrator::HYDRATOR_NAME, SimpleObjectHydrator::class); $configuration->addCustomHydrationMode(ReadOnlyHydrator::HYDRATOR_NAME, ReadOnlyHydrator::class);
与 steevanb/doctrine-stats 集成
steevanb/doctrine-stats 为 Doctrine 添加了大量的统计信息:映射实体数量、懒加载实体数量、合并并计数相同的 SQL 查询、显示 hydration 时间等。
如果您使用这个库,您需要添加 SimpleObjectHydrator 和 ReadOnlyHydrator 的 hydration 时间。
# composer.json { "extra": { "composer-overload-class-dev": { "steevanb\\DoctrineReadOnlyHydrator\\Hydrator\\SimpleObjectHydrator": { "original-file": "vendor/steevanb/doctrine-read-only-hydrator/Hydrator/SimpleObjectHydrator.php", "overload-file": "vendor/steevanb/doctrine-read-only-hydrator/ComposerOverloadClass/Hydrator/SimpleObjectHydrator.php" }, "steevanb\\DoctrineReadOnlyHydrator\\Hydrator\\ReadOnlyHydrator": { "original-file": "vendor/steevanb/doctrine-read-only-hydrator/Hydrator/ReadOnlyHydrator.php", "overload-file": "vendor/steevanb/doctrine-read-only-hydrator/ComposerOverloadClass/Hydrator/ReadOnlyHydrator.php" } } } }