当前位置: 首页 > 知识库问答 >
问题:

条令在水合过程中添加额外的查询,导致“正常”一对一和自引用关系出现n1问题

岳玉书
2023-03-14

新闻使用一对多的自我引用方法相互关联(一个新闻是父新闻,可以有很多孩子)。更重要的是,每个新闻都与事件有正常的(非自引用的)一对一关系。当我运行简单的DQL时:

SELECT n FROM App\Entity\News n WHERE n.parent = :id

然后通过使用默认值设置的getINF方法水合结果,HYDRATION_OBJECT方法中的某个地方进行了额外的查询。

SELECT t0.* FROM event t0 WHERE t0.news_id = 2 AND ((t0.deleted_at IS NULL));
SELECT t0.* FROM gallery t0 WHERE t0.news_id = 2 AND ((t0.deleted_at IS NULL));
SELECT t0.* FROM event t0 WHERE t0.news_id = 1 AND ((t0.deleted_at IS NULL));
SELECT t0.* FROM gallery t0 WHERE t0.news_id = 1 AND ((t0.deleted_at IS NULL));

其中,news\u id=1news\u id=2是第一次查询选择的新闻的子项。

新闻也没有对许多关系进行自我引用(我在这里忽略了它们),但是水合作用对它们没有额外的查询。只有当where语句中涉及到关系时,才会出现问题。

如何繁殖

// news Entity
/**
 * @ORM\Entity(repositoryClass="App\Repository\NewsRepository")
 * @ORM\Table(uniqueConstraints={@UniqueConstraint(name="news_slug_deleted", columns={"slug","deleted_at"})})
 */
class News {
    use SoftDeleteableEntity;

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    /**
     * @Gedmo\Slug(fields={"title"})
     * @ORM\Column(length=128)
     */
    private $slug;
/**
     * @ORM\OneToOne(targetEntity="App\Entity\Gallery", mappedBy="news", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @var Gallery
     */
    private $gallery;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Event", mappedBy="news", cascade={"persist", "remove"}, orphanRemoval=true)
     *
     * @var Event
     */
    private $event;
    /**
     * One News has Many News.
     * @ORM\OneToMany(targetEntity="News", mappedBy="parent")
     */
    private $children;

    /**
     * Many News have One News.
     * @ORM\ManyToOne(targetEntity="News", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
     */
    private $parent;
}
/**
 * @ORM\Entity(repositoryClass="App\Repository\EventRepository")
 * @Gedmo\SoftDeleteable()
 */
class Event
{
    use SoftDeleteableEntity;

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
    /**
     * @ORM\OneToOne(targetEntity="App\Entity\News", inversedBy="event", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $news;

Gallery实体与事件类似,所以我在这里忽略了它。

// News controller

public function index(NewsRepository $newsRepository, $slug)
{
        $news = $newsRepository->findOneBy(['slug' => $slug]);
        $newsRepository->getConnectedNews($news->getId());
}
// news repository

class NewsRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, News::class);
    }
    public function getConnectedNews($newsId) {
        $query = $this->createQueryBuilder('n')->andWhere('n.parent = :id')->setParameter('id', $newsId);
        return $query->getQuery()->getResult(AbstractQuery::HYDRATE_OBJECT);
    }
}

有20个孩子的news的水合作用以: 20*2 1(n*r 1)查询结束,其中:

  • (n) 20是儿童人数

我想防止条令对一对一关系的额外质疑。是我犯了错误,还是我不想要的行为?

总之,我只想得到所有没有一对一关系的自引用子对象,因为我没有要求检索它们,所以应该只使用一个查询来获得所有子对象news,而不需要对每个检索到的“news”对象和每个it的一对一关系进行额外查询。


共有1个答案

邵和硕
2023-03-14

在那个实体中,有两个相反的一对一关系。

逆OneToOne关系不能由Doctrine延迟加载,并且很容易成为性能问题。

如果您真的需要将这些关系映射到反向方(而不仅仅是拥有方),请确保显式地创建适当的连接,或者将这些关联标记为FETCH=EAGER,以便Doctrine为您创建连接。

例如,一个可以避免可怕的“n 1”问题的查询是:

SELECT n, g, e
    FROM App\Entity\News n
    LEFT JOIN n.gallery g
    LEFT JOIN n.event e
WHERE n.parent = :id

你可以在这里或这里阅读更多关于N 1问题的学说。

 类似资料:
  • 我有一个Symfony2应用程序与理论作为ORM。在我的应用程序中,我有两个具有一对多关系的实体。一个实体是用户,多个实体是项目。他们的关系配置如下: 用户: 项目: 问题是当我试图获取及其的列表时,Doctrine为每个用户创建单独的查询来获取它的项目。 查询本身非常简单: 是否可以使用Doctrine在一个查询中自动获取用户的所有相关项? 我使用的是SF 2.7.6和条令库,版本如下:

  • 问题内容: 我需要使用ProcessBuilder构建以下命令: 我尝试使用以下代码: 但是,这会将以下内容传递给系统(已使用Sysinternals Process Monitor进行了验证) 注意前面的引号和后面的两个引号。我需要除去那些多余的引号,因为它们会使调用失败。有谁知道如何做到这一点? 问题答案: 据我了解,由于ProcessBuilder不知道如何将参数传递给命令,因此需要将参数分

  • 现在我需要正在学习‘程序设计’课程的学生名单 如何使用条件查询实现这一点。

  • 问题内容: 因此,我有以下实体: 因此,没有对的引用,这意味着我们具有单向一对多关系。我需要寻找一个by 和。也就是说,找到具有指定posId的供应商,然后在供应商的pos列表中找到一个pos。如何为此编写条件查询? 我尝试使用子查询。我的想法是创建一个子查询,该子查询将获取具有给定条件的a的所有内容。然后,主查询将那些中搜索的一个给定。 问题是我无法编写查询来获取s的s列表。显然,您不能编写以下

  • 实现了一对多的关系,它运行良好。 我的问题是当我运行下面的查询时,如果表有100个员工行,每个员工有两个部门。数据库查询被调用了101次,因为对每个员工都是调用部门查询,要完成调用全部100行需要很长时间,有没有人可以提出替代的解决方案? 输出XML:

  • 问题内容: 嗨,我正在使用Javascript使用以下代码创建带有键和值的对象数组。 结果,我得到了这样的对象数组: 当我尝试将其字符串化并在帖子中发送该JSON时,在我不想要的地方,我使用\和“格式化了错误的JSON,因此当我尝试在C#的代码背后将JSON作为JObject销毁时,我遇到了麻烦。如何使用stringify创建一个干净的JSON 我的JSON现在错了: 我想要一个像这样的JSON对