Doctrine和ManyToOne实体

时间:2017-08-16 11:24:50

标签: php symfony doctrine-orm doctrine

我有两个实体,国家和省,我在省实体建立了多对一关系:

实体/省

public static void GetFormattedParas(Range content, Driver currentDriver)
{
    // TODO add check for tables row end "\r\a" words to ignore them for query

    Paragraphs paras = content.Paragraphs;
    List<Paragraph> paraList = paras.Cast<Paragraph>().ToList();
    List<Range> Ranges = new List<Range>();
    if (paraList != null)
    {
        paraList.RemoveAll(range => range.Range.Text == null);

        paraList.RemoveAll(range => range.Range.Text.Equals("\r\a") && range.Range.Tables.Count != 0 && range.Range.Rows[1].Range.End == range.Range.End);

        for (int i = 0, ParaCount = paraList.Count; i < ParaCount; i++)
        {
            Range range = paraList[i].Range;
            if (range.Font.Shading.BackgroundPatternColorIndex != WdColorIndex.wdNoHighlight
                    || range.HighlightColorIndex != WdColorIndex.wdNoHighlight
                    || range.Shading.BackgroundPatternColorIndex != WdColorIndex.wdNoHighlight)
            {
                Ranges.Add(paraList[i].Range);
            }
        }


        //Ranges = (from range in paraList
        //          where range.Range.Font.Shading.BackgroundPatternColorIndex != WdColorIndex.wdNoHighlight
        //          || range.Range.HighlightColorIndex != WdColorIndex.wdNoHighlight
        //          || range.Range.Shading.BackgroundPatternColorIndex != WdColorIndex.wdNoHighlight
        //          select range.Range).OrderBy(o => o.Start).ToList();

        if (Ranges != null)
        {
            Ranges = Ranges.OrderBy(o => o.Start).ToList();
            if (Ranges.Count > 0)
            {
                //if (Ranges.Count == 1)
                //{
                //    currentDriver.formattedParas.Add(content);
                //}
                //else
                //{
                currentDriver.formattedParas.AddRange(Ranges);
                //}
            }
        }
    }
}

在这里,我使用省实体获得所有结果:

/**
 * @var \AppBundle\Entity\Country
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Country")
 * @ORM\JoinColumn(name="ubicacionpaisid", referencedColumnName="id")
 *
 */
private $ubicacionpaisid;

但是,如果我跑:

 $cb = $this->getDoctrine()
        ->getEntityManager()
        ->getRepository(Province::class)
        ->createQueryBuilder('a');

它返回:

 var_dump($cb->getQuery()->getDQL());

我期望看到的是一个将Country实体连接到SQL中的省实体的查询。

我错过了什么?

3 个答案:

答案 0 :(得分:2)

这可能是因为Doctrine有两种类型的连接。 普通连接和提取连接。在获取连接中,Doctrine将执行2个不同的查询,然后将第二个结果水合回到第一个结果/数据中。

有时也称为懒惰联接。延迟联接是默认行为 您可以通过更改与fetch="EAGER"

的关系来更改此行为
/**
 * @var \AppBundle\Entity\Country
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Country", fetch="EAGER")
 * @ORM\JoinColumn(name="ubicacionpaisid", referencedColumnName="id")
 *
 */

答案 1 :(得分:1)

我意识到有两个人给出的答案只是说使用EAGER加载关联。但我无法推荐。这会对您的项目做出如此多的假设,以及您如何总是希望加入该关联,无论如何,甚至可以cause issues使用表单并创建意外行为。

另外,用户已经显示他们正在使用自定义QueryBuilder调用来获取数据,那么为什么不明确使用连接?

例如:

$cb = $this->getDoctrine()->getEntityManager()->getRepository(Province::class)
    ->createQueryBuilder('p')
    ->select('p, c')
    ->join('p.ubicacionpaisid', 'c')
    ->getQuery()
    ->getResult()
;

或者更好,来自省份库:

return $this->createQueryBuilder('p')
    ->select('p, c')
    ->join('p.ubicacionpaisid', 'c')
    ->getQuery()
    ->getResult()
;

答案 2 :(得分:0)

正如DarkMukke所说......

您是否尝试获取数据?

添加你的关系fetch =&#34; EAGER&#34;

/**
 * @var \AppBundle\Entity\Country
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Country", fetch="EAGER")
 * @ORM\JoinColumn(name="ubicacionpaisid", referencedColumnName="id")
 *
 */
private $ubicacionpaisid;

这也应该获取并加载关联的实体。

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#manytoone