Symfony queryBuilder:查询太多
Symfony queryBuilder: too many queries
我有一个与用户存在多对多关系的实体 table:
/**
* @ORM\ManyToMany(targetEntity="User")
* @ORM\JoinTable(
* name="offer_allowedusers",
* joinColumns={
* @ORM\JoinColumn(name="offer_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
* }
* )
*/
private $allowedUsers;
并且,在表单中,我想显示一个下拉列表(使用 select2)到 select 允许哪些用户:
为此,我在 Form 大楼中做了:
->add('allowedUsers', EntityType::class, [
'class' => 'AppBundle\Entity\User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.username', 'ASC');
},
'label' => 'Allowed users',
'required' => false,
'multiple' => true
])
问题是它对每个用户进行查询,以获取用户名...所以如果我有 500 个用户,它会进行 500 个查询...
如何优化并执行单个查询来获取所有记录?
如果您的 "entity" 没有不需要获取 allowedUsers
的查询,最简单的方法是在字段的 EAGER
中明确定义获取模式注释:
/**
* @ORM\ManyToMany(targetEntity="User", fetch="EAGER")
* @ORM\JoinTable(
* name="offer_allowedusers",
* joinColumns={
* @ORM\JoinColumn(name="offer_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
* }
* )
*/
private $allowedUsers;
在您的 QueryBuilder 中显式创建连接,select 用户和允许的用户。
更新
您还必须加入 select 您的用户个人资料和用户设置 OneToOne 关系,因为 Doctrine 会自动检索 OneToOne 关系获取用户实体的时间。
Doctrine documentation talks about为什么在获取一对一关系的反面时必须执行额外的查询。
->add('allowedUsers', EntityType::class, [
'class' => 'AppBundle\Entity\User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->select('u, au, up, us')
->join('u.allowedUsers', 'au')
->join('u.userProfile', 'up')
->join('u.userSettings', 'us')
->orderBy('u.username', 'ASC')
;
},
'label' => 'Allowed users',
'required' => false,
'multiple' => true
])
我有一个与用户存在多对多关系的实体 table:
/**
* @ORM\ManyToMany(targetEntity="User")
* @ORM\JoinTable(
* name="offer_allowedusers",
* joinColumns={
* @ORM\JoinColumn(name="offer_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
* }
* )
*/
private $allowedUsers;
并且,在表单中,我想显示一个下拉列表(使用 select2)到 select 允许哪些用户:
为此,我在 Form 大楼中做了:
->add('allowedUsers', EntityType::class, [
'class' => 'AppBundle\Entity\User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.username', 'ASC');
},
'label' => 'Allowed users',
'required' => false,
'multiple' => true
])
问题是它对每个用户进行查询,以获取用户名...所以如果我有 500 个用户,它会进行 500 个查询...
如何优化并执行单个查询来获取所有记录?
如果您的 "entity" 没有不需要获取 allowedUsers
的查询,最简单的方法是在字段的 EAGER
中明确定义获取模式注释:
/**
* @ORM\ManyToMany(targetEntity="User", fetch="EAGER")
* @ORM\JoinTable(
* name="offer_allowedusers",
* joinColumns={
* @ORM\JoinColumn(name="offer_id", referencedColumnName="id", onDelete="CASCADE")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
* }
* )
*/
private $allowedUsers;
在您的 QueryBuilder 中显式创建连接,select 用户和允许的用户。
更新
您还必须加入 select 您的用户个人资料和用户设置 OneToOne 关系,因为 Doctrine 会自动检索 OneToOne 关系获取用户实体的时间。
Doctrine documentation talks about为什么在获取一对一关系的反面时必须执行额外的查询。
->add('allowedUsers', EntityType::class, [
'class' => 'AppBundle\Entity\User',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->select('u, au, up, us')
->join('u.allowedUsers', 'au')
->join('u.userProfile', 'up')
->join('u.userSettings', 'us')
->orderBy('u.username', 'ASC')
;
},
'label' => 'Allowed users',
'required' => false,
'multiple' => true
])