我有一个通过单个(!)连接表与多个其他表相关的表 这是一个粗略的草图:
pupils_table (master table)
---
id name
teachers_table (related table 1)
---
id first_name last_name ...
courses_table (related table 2)
---
id start_date end_date ...
join_table (relates master to both (!) related tables)
---
id master_id teacher_id course_id
使用他们的老师和课程获得完整学生记录的标准SQL查询将是:
select p.*, t.*, c.* from pupils_table p
left join join_table jt on jt.master_id = p.id
inner join teachers_table t on t.id = jt.teacher_id
inner join courses_table c on c.id = jt.courses_id
;
但是我很难使用Doctrine的关系映射和QueryBuilder创建这样的查询。我找到的所有示例都使用将主表与一个相关表关联的连接表。
以下是我在实体中尝试的内容,如果我的主人:
/**
* @ORM\Table(name="pupils_table")
*/
class Pupils
{
/**
* @ORM\Column(type="integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Teachers")
* @ORM\JoinTable(name="join_table",
* joinColumns={@ORM\JoinColumn(name="master_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="teacher_id", referencedColumnName="id")} * )
*/
private $teachers;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Courses")
* @ORM\JoinTable(name="join_table",
* joinColumns={@ORM\JoinColumn(name="master_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="course_id", referencedColumnName="id")} * )
*/
private $courses;
...
到目前为止,我没有在教师和课程实体中引入任何特殊关系。
我的查询构建如下:
$qb->select('p', 't', 'c')
->from('AppBundle:Pupils', 'p')
->innerJoin('p.teachers', 't')
->innerJoin('p.courses', 'c')
;
$res = $qb->getQuery()->getResult();
结果是一个带有错误的内部连接序列的SQL查询,结果没有正确地嵌套相关数据(这可以用于这个SQL):
SELECT ... FROM pupils_table c0_
INNER JOIN join_table c3_ ON c0_.id = c3_.master_id
INNER JOIN teachers_table c1_ ON c1_.id = c3_.teacher_id
INNER JOIN join_table c4_ ON c0_.id = c4_.master_id
INNER JOIN courses_table c2_ ON c2_.id = c4_.course_id
如您所见,内部联接之前没有左联接,并且join_table也连接了两次。我知道我没有在我的QueryBuilder命令中明确添加左连接,但是如果连接表只在DocBlock注释中提到并且没有自己的实体(这是文档告诉我的),我该怎么办?
答案 0 :(得分:0)
为了实现这种类型的映射,我会选择将保存对这3个实体的引用的结点实体,并且该结构将生成您在帖子中提到的正确的SQL。以下是我们如何创建和关联联结实体的解释
首先不要直接链接这3个实体,而是用以下方式将您的交汇点实体链接到这3个
PupilTeacherCourseHasMany ---ManyToOne---> Pupils
PupilTeacherCourseHasMany ---ManyToOne---> Teachers
PupilTeacherCourseHasMany ---ManyToOne---> Courses
Pupils ---OneToMany---> PupilTeacherCourseHasMany
Teachers ---OneToMany---> PupilTeacherCourseHasMany
Courses---OneToMany---> PupilTeacherCourseHasMany
小学生课程
/**
* Pupils
* @ORM\Table(name="pupils")
* @ORM\Entity
*/
class Pupils
{
/**
* @ORM\OneToMany(targetEntity="NameSpace\YourBundle\Entity\PupilTeacherCourseHasMany", mappedBy="pupils",cascade={"your options"} )
*/
protected $pupilTeacherCourseHasMany;
}
教师班级
/**
* Teachers
* @ORM\Table(name="teachers")
* @ORM\Entity
*/
class Teachers
{
/**
* @ORM\OneToMany(targetEntity="NameSpace\YourBundle\Entity\PupilTeacherCourseHasMany", mappedBy="teachers",cascade={"your options"} )
*/
protected $pupilTeacherCourseHasMany;
}
课程班级
/**
* Courses
* @ORM\Table(name="courses")
* @ORM\Entity
*/
class Courses
{
/**
* @ORM\OneToMany(targetEntity="NameSpace\YourBundle\Entity\PupilTeacherCourseHasMany", mappedBy="courses",cascade={"your options"} )
*/
protected $pupilTeacherCourseHasMany;
}
<强> PupilTeacherCourseHasMany 强>
/**
* PupilTeacherCourseHasMany
* @ORM\Table(name="pupilteachercoursehasmany")
* @ORM\Entity
*/
class PupilTeacherCourseHasMany
{
/**
* @ORM\ManyToOne(targetEntity="NameSpace\YourBundle\Entity\Pupils", cascade={"your options"})
* @ORM\JoinColumn(name="pupil_id", referencedColumnName="id")
*/
protected $pupils;
/**
* @ORM\ManyToOne(targetEntity="NameSpace\YourBundle\Entity\Teachers", cascade={"your options"})
* @ORM\JoinColumn(name="teacher_id", referencedColumnName="id")
*/
protected $teachers;
/**
* @ORM\ManyToOne(targetEntity="NameSpace\YourBundle\Entity\Courses", cascade={"your options"})
* @ORM\JoinColumn(name="course_id", referencedColumnName="id")
*/
protected $courses;
}
现在要获取所有细节,你的学说查询将是一些像
$qb->select('p', 't', 'c')
->from('AppBundle:Pupils', 'p')
->leftJoin('AppBundle:PupilTeacherCourseHasMany ptc')
->innerJoin('ptc.teachers', 't')
->innerJoin('ptc.courses', 'c')
;
$res = $qb->getQuery()->getResult();