我可以在 postLoad 上模仿 doctrine 的延迟加载吗
Can I mimic doctrine's lazy load on postLoad
我有一个实体 User
,它与名为 Session
的实体具有 OneToMany 关系。
到目前为止一切顺利,我可以执行 $myUser->getSessions()
并获得一个数组,其中包含与 $myUser
相关的所有会话。
Session
也与另一个实体 Moment
.
存在 OneToMany 关系
现在,此 Moment
实体已移动到文档中,因为应用程序的那部分现在位于 MongoDB 数据库中,主要是为了性能问题。
为了保持应用程序 运行 而无需重写大量代码,我创建了一个像这样的 Doctrine Listener :
class DoctrineListenerPostLoad
{
private $container;
private $dm;
public function __construct(Container $container, DocumentManager $dm)
{
$this->dm = $dm;
$this->container = $container;
}
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if($entity instanceof Session)
{
$entity->setMoments(array());
$entity = $args->getEntity();
$moments = $this->dm->getRepository('AppBundle\Document\Moment')->findBy(array('idSession' => $entity->getId()));
$entity->setMoments($moments);
}
}
}
因此,当加载 Session
的实例时,侦听器会在 mongodb 数据库中获取与会话相关的时刻。
但是通过这样做,我失去了学说的惰性负载。当我需要获取用户的所有会话(但不是时刻)时,由于数据量很大,我会得到一个 OutOfMemoryException
,因为它确实加载了时刻。
我知道我可以 "unbind" Session
和 Moment
并在需要时做 DocRepo->findBy(array('idSession' => $entity->getId())
,但我将不得不重写很多很好的工作应用程序上的代码。
还有别的办法吗?就像在实体中加载 DocumentManager(是的!)或检查是否在 PostLoad
?
中调用了 getter
谢谢!
1:使用 Ocramius/ProxyManager 包装数据库调用并延迟,直到有人尝试使用代理集合(应该非常简单)
2:手动制作未初始化的 ODM PersistentCollection
。如果你假装使用 @ReferenceMany(repositoryMethod="getBySession", targetDocument=Moment::class)
作为 moments
,一切都应该正常工作,因为集合将再次使用你编写的存储库方法 lazy-loaded(该方法将被赋予 Session
对象作为第一个参数)。您的 postLoad
大致如下所示:
$mapping = [
'association' => \Doctrine\ODM\MongoDB\Mapping\ClassMetadata::REFERENCE_MANY,
'repositoryMethod' => 'getBySession',
'strategy' => 'setArray',
'targetDocument' => Moment::class,
];
$coll = $this->dm->getConfiguration()->getPersistentCollectionFactory()->create($this->dm, $mapping);
$coll->setOwner($entity, $mapping);
$coll->setInitialized(false);
$entity->setMoments($coll);
请注意,我可能遗漏了一些必需的 $mapping
属性,并且这种方法可能不会永远有效(尽管它不应该在 1.x 中中断)。如果您不想 "cheat" 使用参考映射,您可以将映射 Session
作为文档并直接使用 @ReferenceMany(repositoryMethod="getBySession", targetDocument=Moment::class)
映射时刻,但我不确定 [=28] =].
我有一个实体 User
,它与名为 Session
的实体具有 OneToMany 关系。
到目前为止一切顺利,我可以执行 $myUser->getSessions()
并获得一个数组,其中包含与 $myUser
相关的所有会话。
Session
也与另一个实体 Moment
.
现在,此 Moment
实体已移动到文档中,因为应用程序的那部分现在位于 MongoDB 数据库中,主要是为了性能问题。
为了保持应用程序 运行 而无需重写大量代码,我创建了一个像这样的 Doctrine Listener :
class DoctrineListenerPostLoad
{
private $container;
private $dm;
public function __construct(Container $container, DocumentManager $dm)
{
$this->dm = $dm;
$this->container = $container;
}
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if($entity instanceof Session)
{
$entity->setMoments(array());
$entity = $args->getEntity();
$moments = $this->dm->getRepository('AppBundle\Document\Moment')->findBy(array('idSession' => $entity->getId()));
$entity->setMoments($moments);
}
}
}
因此,当加载 Session
的实例时,侦听器会在 mongodb 数据库中获取与会话相关的时刻。
但是通过这样做,我失去了学说的惰性负载。当我需要获取用户的所有会话(但不是时刻)时,由于数据量很大,我会得到一个 OutOfMemoryException
,因为它确实加载了时刻。
我知道我可以 "unbind" Session
和 Moment
并在需要时做 DocRepo->findBy(array('idSession' => $entity->getId())
,但我将不得不重写很多很好的工作应用程序上的代码。
还有别的办法吗?就像在实体中加载 DocumentManager(是的!)或检查是否在 PostLoad
?
谢谢!
1:使用 Ocramius/ProxyManager 包装数据库调用并延迟,直到有人尝试使用代理集合(应该非常简单)
2:手动制作未初始化的 ODM PersistentCollection
。如果你假装使用 @ReferenceMany(repositoryMethod="getBySession", targetDocument=Moment::class)
作为 moments
,一切都应该正常工作,因为集合将再次使用你编写的存储库方法 lazy-loaded(该方法将被赋予 Session
对象作为第一个参数)。您的 postLoad
大致如下所示:
$mapping = [
'association' => \Doctrine\ODM\MongoDB\Mapping\ClassMetadata::REFERENCE_MANY,
'repositoryMethod' => 'getBySession',
'strategy' => 'setArray',
'targetDocument' => Moment::class,
];
$coll = $this->dm->getConfiguration()->getPersistentCollectionFactory()->create($this->dm, $mapping);
$coll->setOwner($entity, $mapping);
$coll->setInitialized(false);
$entity->setMoments($coll);
请注意,我可能遗漏了一些必需的 $mapping
属性,并且这种方法可能不会永远有效(尽管它不应该在 1.x 中中断)。如果您不想 "cheat" 使用参考映射,您可以将映射 Session
作为文档并直接使用 @ReferenceMany(repositoryMethod="getBySession", targetDocument=Moment::class)
映射时刻,但我不确定 [=28] =].