【问题标题】:Doctrine: Eager load the relationships of a lazy relationship?Doctrine:渴望加载惰性关系的关系?
【发布时间】:2012-09-08 01:45:09
【问题描述】:

我正在使用 Doctrine 2 来绘制学术时间表。以下是关系的简化视图:

  • 一个事件(一对多)
    • 事件有一个类型(多对一)
    • 事件有一个位置(多对一)

使用 $em->find() 我只能获取 ,并带有延迟加载的关系。或者使用带有连接的 DQL,我可以急切地加载整个对象图。有没有介于两者之间的解决方案?

我想获取一个具有延迟加载关系的 class,然后在某些条件下触发 event 关系和所有 event 属性。所以当我打电话给$class->getEventsHydrateAll() 之类的东西时,所有的事件事件类型事件位置都会立即得到补充。

我想我可以通过更新我的 event 架构以将 typelocation 关系标记为 fetch="EAGER" 来实现这一点。但我想控制这种深度水合作用何时发生。

这是我在 class 存储库中进行的一次尝试,但 Doctrine 正在运行单独的查询来查找每个 typelocation

$query = $this->_em->createQuery('
        SELECT c FROM My\Entity\Class c
        WHERE c.id = :classId
');
$query->setParameter('classId', $classId)
      ->setFetchMode('My\Entity\Event', 'type', 'EAGER')
      ->setFetchMode('My\Entity\Event', 'location', 'EAGER');

try {
    return $query->getSingleResult();
} catch (\Doctrine\ORM\NoResultException $e) {
    return NULL;
}

有谁知道 Doctrine 是否支持这个?谢谢!

【问题讨论】:

  • 不确定是否可以处理,因为您有 3 个级别而不是 2 个级别。尝试 ->setFetchMode('My\Entity\Class', 'type', 'EAGER')

标签: php orm doctrine doctrine-orm lazy-loading


【解决方案1】:

TL;DR:

您可以在类属性上使用 EAGER 标志,让它快速加载它的关系。 http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#manytoone

我不确定这是否对你有帮助,但我就是这样解决的。

首先介绍一下我的情况。我目前正在创建一个 OAuth 2 实现,我希望在其上对范围进行细粒度控制。范围非常细化(例如电子邮件、用户名等),然后您可以为每个范围设置单独的权限以进行读取、创建、编辑和删除。

这是一个松散地显示这种关系的数据库图:

所以我的问题是,例如,我如何查看是否允许特定令牌读取(权限)用户名(范围)?

如果我加载令牌,然后获取它的所有权限,然后 foreach read 权限,我检查 username 范围,那么这就是大量的数据库访问。

测试代码:

$permissions = $this->getOAuthHelper()
                    ->getAccessToken($accessToken)
                    ->getPermissions();
$results = [];
foreach ($permissions as $permission) {
    $results[] = $permission->getScope()->getTitle();
}
return $results;

查询日志:

150630 10:49:47    54 Connect   root@localhost on api
150630 10:49:51    54 Query     SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1
                   54 Query     SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3 FROM oauth_permissions t0 INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1'
150630 10:49:52    54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '1'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '2'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '3'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '4'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '5'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '6'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '7'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '8'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '9'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '10'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '11'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '12'
                   54 Query     SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '13'
                   54 Quit

但是,我们可以在这里看到,其中大部分是收集附加到权限的范围。我们可以在权限到作用域的关系上使用 eager 标志来抓取具有权限的作用域:

/**
 * @var Scope
 *
 * @ORM\ManyToOne(targetEntity="OAuthScope", fetch="EAGER")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="scope_id", referencedColumnName="id")
 * })
 */
protected $scope;

注意 ManyToOne 注释上的 fetch="EAGER" 标志。

现在如果我们运行完全相同的代码:

150630 11:00:06    55 Connect   root@localhost on api
150630 11:00:10    55 Query     SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1
150630 11:00:11    55 Query     SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3, t4.id AS id5, t4.title AS title6, t4.brief AS brief7, t4.category_id AS category_id8 FROM oauth_permissions t0 LEFT JOIN oauth_scopes t4 ON t0.scope_id = t4.id INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1'
                   55 Quit

【讨论】:

  • 旁注:图片取自PhpStorm。是的,我正在使用 root 连接到我的数据库,即使在开发过程中,您也可能不应该这样做。不,访问令牌'user-test-token' 不会帮助您破解我们的网站:p
【解决方案2】:

我不确定,但我认为 getSingleResult 会覆盖水合模式。

尝试“执行”,如下例所示:http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#dql-temporarily-change-fetch-mode

【讨论】:

    猜你喜欢
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 2014-02-24
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多