Doctrine 2.5 意外的关联获取行为 [Symfony 3]

Doctrine 2.5 Unexpected association fetch behavior [Symfony 3]

我以这种方式关联了 3 个实体:

别担心,我已经使用注释设置了关联,但我认为以下组合会 lighter/cleaner 来暴露我的问题

Post
  @ORM\ManyToOne(targetEntity="User", fetch="EAGER")
  - author
User
  @ORM\OneToOne(targetEntity="Vip", mappedBy="user", fetch="EAGER")
  - vip
Vip
  # Notice that the primary key of vip is a foreign key on User primary
  @ORM\id
  @ORM\OneToOne(targetEntity="User", inversedBy="peliqan", fetch="EAGER")
  @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
  - user 

如您所见,所有设置为急切获取。

我需要什么?

我想检索帖子集以及 both 用户 & Vip 信息,使用 单个查询(见编辑)

现在,对于每个 post 条目,我都会收到一个额外的查询:

SELECT t0.valid AS valid_1, ...
FROM vip t0
INNER JOIN user t10 ON t0.user_id = t10.id WHERE t0.user_id = ?

时间:

注:
我设法在 getResult() 调用时通过 enforcingQuery::HYDRATE_ARRAY 摆脱了额外的查询。
查询消失了,节省了三分之一的初始时间。
这里的缺点是,在检索关联作为数组时,我无法再利用 Symfony\Component\Serializer\Annotation\Groups 来过滤实体属性,必须手动编辑结果集才能 remove/transform 某些值。

编辑

Wilt 的回答对于原始 post 是可以的。我没有以正确的方式暴露我的问题。我告诉我要检索 Vip 信息,因为我认为这是摆脱上面提到的额外查询的好方法。其实我不需要VIP信息但是省略->leftJoin('u.vip','v')->addSelect('v')使主义发出收集VIP信息的额外查询!有没有办法阻止 doctrine 执行这个查询?

Doctrine2 中有两种连接查询:

1) 常规加入
2) 获取连接

查看 the documentation chapter 14.2.2. Joins 了解更多详情。

因此,如果您想获取加入贵宾,您应该在查询中 addSelectleftJoin 他们,如下所示:

$results = $qb
    ->select('ps')
    ->addSelect('u')->leftJoin('ps.author','u')
    ->addSelect('v')->leftJoin('u.vip','v')
    ->add('where', $qb->expr()->in('ps.id', $ids))
    ->getQuery()->getResult();

更新

评论后更新:

I thought including vip in the result set would be the best way to get rid of the extra query

您无法摆脱额外的查询,因为您无法延迟加载一对一关系的反面。另请参阅 this post 了解更多详情:

This is expected behavior. Inverse sides of one-to-one associations can not be lazy, technically. There is no foreign key on the inverse side, hence it is impossible to decide whether to proxy it or not. We must query for the associated object or join it. Note that this only affects inverse sides of single-valued associations, that is, really only the inverse side of bidirectional one-to-one associations.

  • 一种解决方案可能是反转关系,以便用户成为关系的拥有方。在这种情况下,您至少可以在 User 实体中延迟加载 Vip。延迟加载问题将移至 Vip 端,这意味着您无法在 Viplazy-load 您的 User 了。

  • 否则您可以将查询 return 设置为 Partial object 以防止加载 Vip,但通常您应该非常小心地使用这种方法。