什么时候在 Doctrine2 中维持逆关系是值得的?
在 Doctrine 手册中,尽可能地约束关系,它给出了“消除不必要的关联”和“如果可能的话避免双向关联”的建议。我不明白什么标准会使协会变得“必要”。
我这样说是因为您似乎经常希望从一对多关联的一端而不是从多端进行。例如,我想获取用户的所有活动电话号码,而不是获取所有活动电话号码及其关联的用户。当您必须遍历多个一对多关系时,这一点变得更加重要,例如,如果您想查看过去两天内有未接来电的所有用户(未接来电->电话号码->用户)。
这就是反向关联的简单情况:
SELECT * FROM User u
LEFT JOIN u.PhoneNumbers p WITH p.active
如果有一种方法可以在 DQL 中以相反的方向遍历给定的关系,就像下面的原始 SQL:
SELECT * FROM User u
LEFT JOIN PhoneNumber p ON p.User_id = u.id AND p.active
有人可以解释为什么他们给出这个吗?建议,在什么情况下值得忽略?
-- 编辑 --
如果有缓解因素或其他解决方法,请给我简单的示例代码或链接。
当未定义逆关系时,我看不到任何方法来遍历该关系的逆关系,因此我假设构建自定义 DQL 实际上不是一个解决方案 - 有一些连接对于 SQL 来说是微不足道的,而对于 DQL 来说是不可能的,而且水合可能无论如何也不起作用。这就是为什么我不明白为什么添加逆关系是一个坏主意。
In the Doctrine manual, under Constrain relationships as much as possible, it gives the advice "Eliminate nonessential associations" and "avoid bidirectional associations if possible". I don't understand what criteria would make an association "essential".
I say this because it seems that you would often want to go from the One side of a One-to-Many association rather than from the Many side. For example, I would want to get all of a User's active PhoneNumbers, rather than get all active PhoneNumbers and their associated User. This becomes more important when you have to traverse multiple One-to-Many relations, e.g. if you wanted to see all Users with a MissedCall from the last two days (MissedCall->PhoneNumber->User).
This is how the simple case would look with an inverse association:
SELECT * FROM User u
LEFT JOIN u.PhoneNumbers p WITH p.active
It would make it more sensible if there were a way to go across a given relation in the opposite direction in DQL, like the following raw SQL:
SELECT * FROM User u
LEFT JOIN PhoneNumber p ON p.User_id = u.id AND p.active
Can someone explain why they give this advice, and in what cases it would be worth ignoring?
-- Edit --
If there are mitigating factors or other workarounds, please give me simple example code or a link.
I do not see any way to traverse a relation's inverse when that inverse is not defined, so I'm going to assume that building custom DQL is not in fact a solution -- there are some joins that are trivial with SQL that are impossible with DQL, and hydration probably wouldn't work anyway. This is why I don't understand why adding inverse relations is a bad idea.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 Doctrine,我仅在需要时定义关系。这意味着定义的所有关系实际上都在代码库中使用。
对于有大型团队在项目的不同领域工作的项目,并不是每个人都会习惯 Doctrine、它的当前配置以及急切/延迟加载关系。如果您在不必要且可能没有意义的情况下定义双向关系,则可能会导致对以下数据的额外查询:
只定义必要的关系将允许您更好地控制关于您和您的团队如何遍历数据并减少额外或过大的查询
更新时间 2011 年 8 月 22 日
我所说的基本关系是指您使用的关系。定义一个你不会使用的关系是没有意义的。例如:
\Entity\Post
与\Entity\User
和\Entity\Comment
都有已定义的关系$post->user
获取作者$post->comments
获取所有评论\Entity\User
与\Entity\Post
和\Entity\Comment
都有已定义的关系$user->posts
获取所有用户帖子$user->comments
获取所有用户评论\Entity\Comment< /code> 仅与- 使用
- 无法使用
\Entity\User
有关系$comment->user
获取作者$comment->post
,因为我没有在我的应用程序中检索到它所属的帖子我不会将它们视为“逆”关系。如果双向使用数据有意义,则将它们视为“双向”。如果它没有意义,或者您不会以这种方式使用数据,请不要定义它。
我希望这是有道理的
Using Doctrine, I only define relationships when they're needed. This means that all of the relationships defined are actually used in the codebase.
For projects with a large team working on different areas of the project, not everyone will be accustomed to Doctrine, it's current configuration, and eager/lazy loading relationships. If you define bi-directional relationships where they aren't essential and possibly don't make sense, it could potentially lead to extra queries for data that:
Defining only essential relationships will allow you greater control over how you and your team traverse through your data and reduce extra or overly large queries
Updated 22/08/2011
By essential relationships, I mean the ones you use. It doesn't make sense to define a relationship you wouldn't use. For example:
\Entity\Post
has a defined relationship to both\Entity\User
and\Entity\Comment
$post->user
to get author$post->comments
to get all comments\Entity\User
has a defined relationship to both\Entity\Post
and\Entity\Comment
$user->posts
to get all user posts$user->comments
to get all user comments\Entity\Comment
only has a relationship to\Entity\User
$comment->user
to get author$comment->post
as I don't retrieve the post it belongs to in my applicationI wouldn't think of them as "Inverse" relationships. Think of them as "Bi-directional", if using the data in both directions makes sense. If it doesn't make sense, or you wouldn't use the data that way around, don't define it.
I hope this makes sense
我认为这是一个很好的问题,我期待其他人的答案。
一般来说,我将您在下面引用的建议解释为以下经验法则:
如果我不需要访问实体内的(反向)关联,那么我通常将其设为单向。在您的用户和(错过的)呼叫示例中,我可能会保持单向,并让某些服务类或存储库处理将自定义 DQL 放在一起,以应对当我需要获取最近错过呼叫的所有用户的列表时出现的奇怪情况。这是我认为例外的情况 - 大多数时候,我只对特定用户的呼叫感兴趣,因此单向关系有效(至少在我有这么多记录以至于我觉得需要优化之前) 。
I think this is a great question, and am looking forward to others' answers.
Generally, I've interpreted the advice you cited in the down to the following rule of thumb:
If I don't need to access the (inverse) association inside my entity, then I typically make it unidirectional. In your example of users and (missed) calls, I'd probably keep it unidirectional, and let some service class or repository handle putting together custom DQL for the odd occurrence when I needed to get a list of all users with recent missed calls. That's a case I'd consider exceptional -- most of the time, I'm just interested in a particular user's calls, so the unidirectional relationship works (at least until I've got so many records that I feel the need to optimize).