我有三个实体:SequenceRun
有一个MaterialTypeString
,并且有许多User
。 即SequenceRun
和MaterialTypeString
之间存在一对多关系,SequenceRun
和User
之间存在多对多关系。
序列运行.php:
/**
* @ORMManyToOne(targetEntity="MaterialTypeStrings", inversedBy="sequenceRuns")
* @ORMJoinColumn(name="material_type_strings_id", referencedColumnName="id")
*/
private $materialTypeString;
/**
* Many Groups have Many Users.
* @ORMManyToMany(targetEntity="FOSUser", mappedBy="sequenceRuns")
*/
private $users;
现在无需急于加载我的索引方法:
/**
* @Route("/sequence_run/index", name="sequence_run_index")
*/
public function indexAction() {
// Grab all experiments from database and hand them to template.
$repository = $this->getDoctrine()->getRepository('AppBundle:SequenceRun');
$sequence_runs = $repository->findAll();
return $this->render('sequence_run/index.html.twig',['sequence_runs' => $sequence_runs]);
}
为单个SequenceRun
对象生成 4 个查询:
SELECT t0.username AS username_1, t0.username_canonical AS username_canonical_2, t0.email AS email_3, t0.email_canonical AS email_canonical_4, t0.enabled AS enabled_5, t0.salt AS salt_6, t0.last_login AS last_login_7, t0.confirmation_token AS confirmation_token_8, t0.password_requested_at AS password_requested_at_9, t0.roles AS roles_10, t0.id AS id_11, t0.dn AS dn_12, t0.cn AS cn_13, t0.department AS department_14, t0.department_dn AS department_dn_15, t0.from_bio_control AS from_bio_control_16, t0.password AS password_17 FROM fos_user t0 WHERE t0.id = ? LIMIT 1
Parameters: [0 => 96]
SELECT t0.id AS id_1, t0.start_date AS start_date_2, t0.end_dat AS end_dat_3, t0.kit AS kit_4, t0.run_coverage_target AS run_coverage_target_5, t0.read_length AS read_length_6, t0.created_at AS created_at_7, t0.updated_at AS updated_at_8, t0.material_type_strings_id AS material_type_strings_id_9 FROM sequence_run t0
Parameters: []
SELECT t0.username AS username_1, t0.username_canonical AS username_canonical_2, t0.email AS email_3, t0.email_canonical AS email_canonical_4, t0.enabled AS enabled_5, t0.salt AS salt_6, t0.last_login AS last_login_7, t0.confirmation_token AS confirmation_token_8, t0.password_requested_at AS password_requested_at_9, t0.roles AS roles_10, t0.id AS id_11, t0.dn AS dn_12, t0.cn AS cn_13, t0.department AS department_14, t0.department_dn AS department_dn_15, t0.from_bio_control AS from_bio_control_16, t0.password AS password_17 FROM fos_user t0 INNER JOIN users_sequence_runs ON t0.id = users_sequence_runs.fosuser_id WHERE users_sequence_runs.sequence_run_id = ?
Parameters: [0 => 2]
SELECT t0.id AS id_1, t0.type AS type_2 FROM material_type_strings t0 WHERE t0.id = ?
Parameters: [0 => 5]
如果我将fetch = "EAGER"
添加到MaterialTypeString
,它会删除最后一个查询(如预期的那样(。但是,如果我添加也将其添加到User
我仍然会收到 3 个查询。
eager
加载是否适用于多对多关系,还是必须使用DQL
并手动编写查询?(如果是这样,那会是什么样子?
你想实现什么?如果要对 dB 进行单个查询,在其中获取所有需要的实体,则确实需要手动编写自定义查询,这不是急切或延迟加载的问题。
你可以写这样的东西
$sequence_runs=$repository->createQueryBuilder('sr')->addSelect(['mts', 'fu'])
->leftJoin('sr.materialTypeString', 'mts')
->leftJoin('sr.users', 'fu')
->getQuery()->getResult();
当您希望 Doctrine 执行所有需要的查询(无论您是否在代码中使用关联(时,您可以使用预先加载,而使用延迟加载来仅在代码中访问关联时才完全冻结关联,但如果您访问代码中的所有关联,查询的数量将是相同的。
关键是:
您是否显示实体的分页列表?然后,尝试使用 DQL 或查询生成器编写自己的查询,获取加载所有必要的实体以符合您的视图。
您是否显示单个实体?然后通过延迟加载您的关联从存储库中获取它,让 Doctrine 完成这项工作!