学说 2 与表的区别是一比一的相同关系



我有 2 个具有相同一对一关系的实体:

class FirstEntity {
...
/**
* @var AppEntityThirdEntity
*
* @ORMOneToOne(targetEntity="AppEntityThirdEntity")
*/
protected $thirdEntity;

class SecondEntity {
...
/**
* @var AppEntityThirdEntity
*
* @ORMOneToOne(targetEntity="AppEntityThirdEntity")
*/
protected $thirdEntity;

$thirdEntity字段不能为空。 有没有办法通过查询生成器或本机查询(如 array_diff() 操作)返回结果:

$firsts = array_map(function (FirstEntity $firstEntity) {
return $firstEntity->getThirdEntity()->getId();
}, $this->em->getRepository(FirstEntity::class)->findAll());
$seconds = array_map(function (SecondEntity $secondEntity) {
return $secondEntity->getThirdEntity()->getId();
}, $this->em->getRepository(SecondEntity::class)->findAll());
return array_diff($firsts, $seconds);

所以我想要的是链接到FirstEntity但不链接到SecondEntity的所有ThirdEntity的列表。

实现此目的的最高性能方法是使用本机查询或查询生成器(或多个本机查询/查询构建器)。这样,数据库将为您完成所有过滤,这意味着Doctrine不必做太多工作。

查询生成器是最简单的方法,但确实要求您还要求从ThirdEntity映射到FirstEntitySecondEntity- 以下代码假定您已经准备好了该映射。

$qb = $em->createQueryBuilder();
$result = $qb->select('t')->from('ThirdEntity', 't')
->innerJoin('t.firstEntity', 'f')
->leftJoin('t.secondEntity', 's')
->where($qb->expr()->isNull('s.id'));
->getQuery()->getResult();

这里发生的情况是,我们要求数据库获取所有ThirdEntity记录,inner join所有FirstEntity记录(因此不包括没有FirstEntityThirdEntity)。然后我们用SecondEntityleft join这一点,这意味着如果ThirdEntity也链接到一个SecondEntity,它的数据就可以过滤了,否则我们会得到所有SecondEntity列的NULL。最后一步是仅选择那些没有SecondEntity的记录(这意味着其 ID 为null)。

在确切的数据集上,这种"一个查询"方法可能无法为您提供最佳性能。首先选择与FirstEntity相关的所有ThirdEntity项的 ID,然后(在单独的查询中,在该查询中使用该 ID 列表作为参数)筛选出那些也与SecondEntity相关的项可能会更快。反过来做这两件事也可能更快。不过我并不期待这一点,所以我们将把它留给另一个问题(或这个问题的另一个答案)。

相关内容

  • 没有找到相关文章

最新更新