7

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

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

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

我想获取一个具有延迟加载关系的,然后在某些条件下触发事件关系和所有事件属性的急切加载。所以当我调用类似的东西时$class->getEventsHydrateAll(),所有的事件事件类型以及事件位置都会立即被水合。

我想我可以通过更新我的事件模式来将类型位置关系标记为fetch="EAGER". 但我想控制这种深度水合作用何时发生。

这是我在我的存储库中进行的一次尝试,但 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 是否支持这一点?谢谢!

4

2 回答 2

5

TL;博士:

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

我不确定这是否会对您有所帮助,但这就是我解决它的方法。

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

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

在此处输入图像描述

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

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

测试代码:

$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;

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

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

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
于 2015-06-30T11:02:25.907 回答
-1

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

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

于 2013-06-26T12:48:54.463 回答