【问题标题】:How to prevent redundant lookups when joining entity relationships?加入实体关系时如何防止冗余查找?
【发布时间】:2012-11-27 12:59:56
【问题描述】:

我正在加快使用 Symfony 2 和 Doctrine 的速度,并且在执行大量不必要的数据库查找以与连接的实体进行水合时遇到困难。

在使用子对象执行联合查询后,子对象会自动从数据库中提取其其他映射。尽管我没有尝试访问它的任何属性,但它正在这样做。就好像它们在 find 查询中被访问。

我的示例如下所示 - 名为 PersonBuilding 的实体都加入了名为 Place 的实体:

class Person {
    /**
     * Where this person lives
     * @var Place $Home
     * 
     * @ORM\OneToOne(targetEntity="Place", cascade={"persist"}, inversedBy="Resident" )
     * @ORM\JoinColumn(name="place_id", referencedColumnName="id")
     */
    private $Home;
}

class Building {

    /**
     * Where this building stands
     * @var Place $Site
     * 
     * @ORM\OneToOne(targetEntity="Place", cascade={"persist"}, inversedBy="Landmark" )
     * @ORM\JoinColumn(name="place_id", referencedColumnName="id")
     */
    private $Site;
}

class Place {
    /**
     * Reverse mapping
     * @var Person $Resident
     * 
     * @ORM\OneToOne(targetEntity="Person", mappedBy="Home")
     */   
    private $Resident;

    /**
     * Reverse mapping
     * @var Building $Landmark
     * 
     * @ORM\OneToOne(targetEntity="Building", mappedBy="Site")
     */   
    private $Landmark;
}

我的 Person 存储库连接如下所示:

/**
 * @override
 * @return Person
 */
public function find( $id ){
    $query = $this->getEntityManager()
        ->createQuery('
            SELECT p, h
            FROM MyBundle:Person p
            JOIN p.Home h
            WHERE p.id = :id'
        )->setParameter('id', $id);
    return $query->getSingleResult();
}

如何防止 Place 在 find 操作期间单独获取其 Building 关系?有什么我可以传递给 Query 实例来阻止这种情况的吗?

【问题讨论】:

  • 我上传了一个示例包。如果没有人可以复制此错误,那么我的设置一定有问题。 static.timwhitlock.info/MyExampleBundle.tar.gz
  • 我可以通过在查询中设置这个来防止自动获取:$query->setHint( Query::HINT_FORCE_PARTIAL_LOAD, true ); 问题是当我确实想要它时它会杀死延迟加载。

标签: php symfony doctrine


【解决方案1】:

fetch 选项添加到您的映射中。

像这样:

班级地点{

/**
 * Reverse mapping
 * @var Person
 * 
 * @ORM\OneToOne(targetEntity="Person", mappedBy="Home", fetch="EXTRA_LAZY")
 */   
private $Resident; 

}

【讨论】:

  • 恐怕不适合我。无论如何,懒惰应该足够了。我最初的加入有一些东西可以防止懒惰。
  • 这不起作用的唯一原因是如果你有$place->getResident()在某个地方打电话
  • 这是我的想法,但我没有。
  • 如果映射被定义为惰性,则原则没有理由提取额外的数据,原则将忽略它除非明确请求数据。缓存、偷偷摸摸的服务、树枝扩展、模板中的访问、表单中的访问、未加载的自定义存储库和 ->find 进入默认设置。不要假设您有极端情况,请先重新检查 100 次。
  • 公平评论。我已将代码简化为示例包并上传。我仍然可以在其中复制额外的查询,并且不知道哪里可以引用 Place::Resident,我什至排除了 Resident getter 方法。 static.timwhitlock.info/MyExampleBundle.tar.gz
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 2018-10-30
相关资源
最近更新 更多