无需加入或新的sql请求即可获取实体子对象ID

时间:2015-12-04 16:20:11

标签: symfony doctrine-orm doctrine

示例I有一个具有联系人的实体用户。如何在不加入联系表的情况下获取联系人ID。

$user = $entityManager->userRepository->findUserById(1);
$contactId = $user->getContact()->getId();

当调用`getContact()时,从DB加载整个联系人。如何在不添加findUserById连接的情况下避免此SQL请求。我只需要在我的用户表中联系我,但没有像$ user-> getContactId()这样的简单函数。

3 个答案:

答案 0 :(得分:1)

看看这篇文章Getting only ID from entity relations without fetching whole object in Doctrine。我在ManyToOne关系中测试了一个简单的例子,并且未加载相关对象。

答案 1 :(得分:1)

Your situation sounds perfect for the Doctrine Second Level Cache

http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html

With this, the first query will be gotten from DB but every subsequent query will be from the second level cache, plus if you change the data using doctrine then the cache is automatically updated. For this reason, I suggest you set a very long time for the cache my personal favourite is 1 month approx 2592000 seconds.

Enable it in your user entity like so

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;

/**
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="users_region")
* @ORM\Table(
*   name="site_users",
*   indexes={
*       @ORM\Index(name="username_index", columns={"username"}),
*       @ORM\Index(name="email_index", columns={"email"}),
*       @ORM\Index(name="enabled_index", columns={"enabled"}),
*       @ORM\Index(name="last_login_index", columns={"last_login"})
*   }
*)
*/
class User extends BaseUser 
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

......

Then in your config.yml like so

    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
            default:
                connection: default
                auto_mapping: true
                naming_strategy: doctrine.orm.naming_strategy.underscore
                second_level_cache:
                    enabled:            true
#                    region_lock_lifetime: 60
                    region_lifetime:    300
                    log_enabled:        %kernel.debug%
                    region_cache_driver: apc
                    regions: 
                        users_region: 
                            region_lifetime:    2592000
                            region_cache_driver: apc

............

More information here

http://symfony.com/doc/master/bundles/DoctrineBundle/configuration.html

Note this method also ensure that the popular check for an authenticated user $user = $this->getUser(); does not hit your DB as well.

答案 2 :(得分:0)

我建议您更改特定查询中的获取模式,如文档中所述here

因此,您可以按如下方式描述您的查询:

// Supposing this method in the repository class
public function findUserById($idUser)
{
$qb =  $this->createQueryBuilder('u')
        ->where("u.id = :idUser")
        ->setParameter("idUser", $idUser);

        $query = $qb->getQuery();
        // Describe here all the entity and the association name that you want to fetch eager
        $query->setFetchMode("YourBundle\\Entity\\Contract", "contract", ClassMetadata::FETCH_EAGER);
        ...

return $qb->->getResult();
}

NB:

  

在查询期间更改提取模式只能是一对一的   和多对一的关系。

希望这个帮助