使用 QueryBuilder 时停止在doctrine2中查询相关实体

发布于 2024-12-25 15:02:26 字数 2616 浏览 1 评论 0原文

我有两个具有一对一关系的实体用户和配置文件。

$qb = $this->getDoctrine()->getEntityManager()->createQueryBuilder();
$qb->add('select', 'u')
   ->add('from', '\Acme\TestBundle\Entity\User u')
   ->add('orderBy', 'u.id DESC');
$query = $qb->getQuery();
$customer = $query->execute();

当我检查 Symfony Profiler 中的查询数量时,我可以看到在用户表中的 n 个用户的配置文件表上触发的查询数量。有什么办法可以停止查询配置文件表。

如果有更好的实现方法,请告诉我。

预先感谢

添加实体类

class User
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $email
     *
     * @ORM\Column(name="email", type="string", length=255)
     */
    private $email;

    /**
     * @var Acme\TestBundle\Entity\Profile
     * 
     * @ORM\OneToOne(targetEntity="Acme\TestBundle\Entity\Profile", mappedBy="user")
     */
    private $profile;

}

class Profile
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer $user_id
     *
     * @ORM\Column(name="user_id", type="integer")
     */
    private $user_id;

    /**
     * @var string $user_name
     *
     * @ORM\Column(name="user_name", type="string", length=100)
     */
    private $user_name;

    /**
     * @var Acme\TestBundle\Entity\User
     * 
     * @ORM\OneToOne(targetEntity="Acme\TestBundle\Entity\User", inversedBy="profile")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;    

}

mysql日志的响应

120110 15:14:29    89 Connect   root@localhost on test
           89 Query SET NAMES UTF8
           89 Query SELECT c0_.id AS id0, c0_.email AS email1, c0_.password AS password2, c0_.is_demo_user AS is_demo_user3, c0_.status AS status4, c0_.current_service AS current_service5, c0_.registration_mode AS registration_mode6, c0_.verification_code AS verification_code7, c0_.account_type AS account_type8, c0_.activated_date AS activated_date9, c0_.status_updated_at AS status_updated_at10, c0_.created_at AS created_at11, c0_.updated_at AS updated_at12 FROM user c0_ WHERE c0_.id = 1 ORDER BY c0_.email ASC
           89 Query SELECT t0.id AS id1, t0.user_id AS user_id2, t0.user_name AS user_name3, t0.age AS age4, t0.created_at AS created_at5, t0.updated_at AS updated_at6, t0.user_id AS user_id7 FROM profile t0 WHERE t0.user_id = '1'
           89 Quit  

I am having two entities User and Profile with one to one relationship.

$qb = $this->getDoctrine()->getEntityManager()->createQueryBuilder();
$qb->add('select', 'u')
   ->add('from', '\Acme\TestBundle\Entity\User u')
   ->add('orderBy', 'u.id DESC');
$query = $qb->getQuery();
$customer = $query->execute();

When i Check the number of queries in Symfony profiler I could see n number for queries triggered on Profile table for n users in User table. Is there any way where I can stop the querying of the Profile table.

Please let me know if there is better way of implementing it.

Thanks in advance

Added Entity Classes

class User
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $email
     *
     * @ORM\Column(name="email", type="string", length=255)
     */
    private $email;

    /**
     * @var Acme\TestBundle\Entity\Profile
     * 
     * @ORM\OneToOne(targetEntity="Acme\TestBundle\Entity\Profile", mappedBy="user")
     */
    private $profile;

}

class Profile
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer $user_id
     *
     * @ORM\Column(name="user_id", type="integer")
     */
    private $user_id;

    /**
     * @var string $user_name
     *
     * @ORM\Column(name="user_name", type="string", length=100)
     */
    private $user_name;

    /**
     * @var Acme\TestBundle\Entity\User
     * 
     * @ORM\OneToOne(targetEntity="Acme\TestBundle\Entity\User", inversedBy="profile")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;    

}

Response from the mysql log

120110 15:14:29    89 Connect   root@localhost on test
           89 Query SET NAMES UTF8
           89 Query SELECT c0_.id AS id0, c0_.email AS email1, c0_.password AS password2, c0_.is_demo_user AS is_demo_user3, c0_.status AS status4, c0_.current_service AS current_service5, c0_.registration_mode AS registration_mode6, c0_.verification_code AS verification_code7, c0_.account_type AS account_type8, c0_.activated_date AS activated_date9, c0_.status_updated_at AS status_updated_at10, c0_.created_at AS created_at11, c0_.updated_at AS updated_at12 FROM user c0_ WHERE c0_.id = 1 ORDER BY c0_.email ASC
           89 Query SELECT t0.id AS id1, t0.user_id AS user_id2, t0.user_name AS user_name3, t0.age AS age4, t0.created_at AS created_at5, t0.updated_at AS updated_at6, t0.user_id AS user_id7 FROM profile t0 WHERE t0.user_id = '1'
           89 Quit  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情话难免假 2025-01-01 15:02:26

你的答案就在这里!!

http://docs.doctrine -project.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html

“在许多情况下,实体之间的关联可能会变得相当大。即使在简单的情况下,在像博客这样的场景中,您总是必须假设一个帖子会吸引数百条评论,如果您访问一个关联,它总是会完全加载到内存中,这可能会导致非常严重的性能问题。如果您的关联包含数百或数千个实体,则

在 Doctrine 2.1 中为关联引入了一个名为“Extra Lazy”的功能,默认情况下,关联将被标记为“Lazy”,这意味着关联的整个集合对象都被标记为“Lazy”。如果您将关联标记为额外惰性,则可以在不触发集合的完全加载的情况下调用集合上的以下方法:“

<?php
namespace Doctrine\Tests\Models\CMS;

/**
 * @Entity
 */
class CmsGroup
{
    /**
     * @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
    */
    public $users;
}

有点晚了,但它可能会对其他人有所帮助!

Your answer is here!!

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/extra-lazy-associations.html

"In many cases associations between entities can get pretty large. Even in a simple scenario like a blog. where posts can be commented, you always have to assume that a post draws hundrets of comments. In Doctrine 2.0 if you accessed an association it would always get loaded completly into memory. This can lead to pretty serious performance problems, if your associations contain several hundrets or thousands of entities.

With Doctrine 2.1 a feature called Extra Lazy is introduced for associations. Associations are marked as Lazy by default, which means the whole collection object for an association is populated the first time its accessed. If you mark an association as extra lazy the following methods on collections can be called without triggering a full load of the collection:"

<?php
namespace Doctrine\Tests\Models\CMS;

/**
 * @Entity
 */
class CmsGroup
{
    /**
     * @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
    */
    public $users;
}

It's a bit late, but it might help others out there!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文