多对多关联场景下,如何编写带关联表条件的Doctrine DQL?
嘿,我来帮你搞定这个多对多关联下带关联表条件的DQL问题!
多对多关联的DQL写法(对应你的SQL示例)
首先明确:Doctrine的DQL是面向实体的查询语言,通常不需要像原生SQL那样手动关联中间表(除非有特殊需求,比如中间表包含额外业务字段)。下面分两种场景给你说明:
场景1:利用实体关联自动处理中间表
假设你的Books实体已经配置了和Account的多对多关联(比如Books类里有$accounts属性,通过注解/XML指定关联表为account_books),那么和你提供的SQL等价的DQL可以这么写:
SELECT b, a.id FROM App\Entity\Books b LEFT JOIN b.accounts a WITH a.id = 17
关键细节解释:
LEFT JOIN b.accounts a:通过Books实体的关联属性accounts直接关联Account实体,Doctrine会自动帮你处理中间表account_books的JOIN逻辑WITH a.id = 17:这个关键字用来在JOIN阶段添加条件,和你SQL里ON ... AND account_books.account_id = 17的效果完全一致——既保留所有Books记录(LEFT JOIN特性),又只关联account_id=17的账户数据
场景2:手动关联中间表(适合中间表有额外字段的情况)
如果你的中间表account_books有额外业务字段(比如关联创建时间、备注等),并且你已经为它创建了对应的实体(比如AccountBooks),可以显式JOIN中间表来完全匹配你的SQL结构:
SELECT b, acc.id FROM App\Entity\Books b LEFT JOIN App\Entity\AccountBooks ab WITH ab.books = b AND ab.account = 17 LEFT JOIN ab.account acc
这个写法会生成和你提供的原生SQL几乎完全一致的查询语句,手动指定了中间表的关联条件。
重要提醒:
千万别把WITH换成WHERE!如果用WHERE a.id = 17,会把LEFT JOIN变成INNER JOIN的效果,直接过滤掉没有关联到account_id=17的书籍,这和你原SQL的需求不符。
内容的提问来源于stack exchange,提问作者YuraV
相关产品推荐
相关产品推荐

