与Doctrine2重新连接的一对多数据库表

时间:2014-11-14 10:46:51

标签: php database symfony doctrine-orm

我有以下相关数据库表的设置:

Organization
+--------+---------+
|   id   | integer |
+--------+---------+
|  name  | string  |
+--------+---------+

Division
+---------------+---------+
|      id       | integer |
+--------+----------------+
|organization_id| integer |
+---------------+---------+
|      name     | string  |
+---------------+---------+

Subdivision
+---------------+---------+
|      id       | integer |
+--------+----------------+
|  division_id  | integer |
+---------------+---------+
|      name     | string  |
+---------------+---------+

我正在使用带有Doctrine2 ORM的Symfony2FOSRestBundle

现在我对协会映射感到困惑。

当我需要组织时,我希望得到以下内容

{
    id: 1,
    name: "organization1",
    divisions: [
       {
            id: 1,
            organization_id: 1,
            name: "division1"
            subdivisions: [
               {
                  id: 1,
                  division_id: 1,
                  name: "subdivision1"
               }
            ]
       }
    ]
}

我想出了这个,并使用了One-To-Many bidirectional association mapping of Doctrine

让我头疼的是这种关系的相反方向。   如果我需要一个特定的细分,我想得到以下内容:

{
    id: 1,
    division_id: 1,
    name: "subdivision1",
    division: {
            id: 1,
            organization_id: 1,
            name: "division1"
            organization: {
                  id: 1,
                  name: "organization"
            }
       }
    ]
}

但我明白了:

{
   id: 1,
   division_id: 1,
   name: "subdivision1",
   division: {
       id: 1,
       organization_id: 1,
       name: "division1",
       organization: {
           id: 1,
           name: "organization1",
           divisions: [/* ..list of all the other divisions.. */]
       },
       subdivisions: [/* ..list of all the other subdivisions.. */]
   }

}

如何使用Doctrine从返回的数据中删除细分和分区?

因为我只需要细分,它所属的部门和部门所属的组织。列出所有树需要大量数据和时间,而我并不需要全部。

修改

我正在使用以下内容来检索记录(每件事都按预期工作):

$organization = $this
        ->getDoctrine()
        ->getRepository('MyTestBundle:Organization')
        ->find($id);

$organization = $this
        ->getDoctrine()
        ->getRepository('MyTestBundle:Organization')
        ->findAll();

反方向:

$subdivision = $this
        ->getDoctrine()
        ->getRepository('MyTestBundle:Subdivision')
        ->find($id);

这将生成以下SQL:

SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.id = ? ["11"] []
SELECT t0.id AS id1, t0.organization_id AS organization_id2, t0.name AS name3, t0.organization_id AS organization_id4 FROM Division t0 WHERE t0.id = ? [16] []
SELECT t0.id AS id1, t0.name AS name2 FROM Organization t0 WHERE t0.id = ? [15] []
SELECT t0.id AS id1, t0.organization_id AS organization_id2, t0.name AS name3, t0.organization_id AS organization_id4 FROM Division t0 WHERE t0.organization_id = ? [15] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [15] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [18] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [19] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [45] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [49] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [51] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [56] []
SELECT t0.id AS id1, t0.division_id AS division_id2, t0.name AS name3, t0.division_id AS division_id4 FROM Subdivision t0 WHERE t0.division_id = ? [16] []

1 个答案:

答案 0 :(得分:0)

$subdivision ... ->find($id)替换为

$subdivision = $this
    ->getDoctrine()
    ->getRepository('MyTestBundle:Subdivision')
    ->createQueryBuilder('s')
    ->leftJoin('s.division', 'd')
    ->leftJoin('d.organization', 'o')
    ->where('s.id = :id')
    ->setParameter('id', $id)
    ->getQuery()
    ->getSingleResult();

这应该已经降低了Doctrine请求的数量。当然divisions的{​​{1}}属性仍然存在,但内容不会自动加载第一个查询。如果您通过organization访问该属性,则将从数据库加载内容。它是Doctrine的一个特性,可以在不让开发人员考虑的情况下加载必要的数据。当然,它不是最高效的方式,你必须根据自己的需要采用它。请查看lazy loading及相关主题。