简体   繁体   中英

Symfony queryBuilder: too many queries

I have an entity with a ManyToMany relationship with the User 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;

And, in the form, I want to display a dropdown (using select2 ) to select which users are allowed:

在此输入图像描述

To do that, I made, in the Form building:

->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
    ])

The problem is that it makes a query for each user, to get the username... So if I have 500 users, it makes 500 queries...

在此输入图像描述

How can optimize and do a single query to fetch all the records?

Explicitly create the join in your QueryBuilder, and select both the user and allowed users.

UPDATE

You must also join and select your user profile and user settings OneToOne relations because Doctrine automatically retrieves OneToOne relations them any time you fetch the User entity.

The Doctrine documentation talks about why it has to perform an extra query when fetching the inverse side of a one-to-one relation.

->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
])

If you don't have queries to your "entity" that don't need to fetch allowedUsers the simplest way would be to explicitly define fetch mode as EAGER in the field's annotations:

/**
 * @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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM