学说2 - 如何处理不同步的数据库/实体

时间:2011-01-03 20:01:05

标签: php orm doctrine-orm

我正在开发一个PHP Web应用程序,我希望将Doctrine 2.0用于ORM功能。但是,我遇到了一个特定类型的查询时遇到的重大问题。

考虑一个包含Foo和Bar Entities的简单域模型。 Foo实体包含许多条形,条形可能被标记为活动。

/** @Entity */
class Foo
{
    /** @OneToMany(targetEntity="Bar", mappedBy="foo") */
    protected $bars;

    /** Returns Bars marked as active. */
    public function getActiveBars()
    {
        // XXX What goes here?
    }
}

/** @Entity */
class Bar
{
    /** @ManyToOne(targetEntity="Foo", inversedBy="bar") */
    protected $foo;

    /** @Column(type="boolean") */
    protected $active;

    /** ...setter omitted for clarity... */
}

我的问题是:应该在getActiveBars方法中放置哪些代码?


以下代码可以正常工作,但当数据库中有许多非活动Bar对象时,性能将成为问题。迭代Bar集合会导致对数据库执行大型查询。

function getActiveBars()
{
    $ret = array();
    foreach($this->bars as $bar) {
        if ($bar->isActive()) $ret[] = $bar;
    }
    return $ret;
}

在getActiveBar()中执行诸如SELECT b FROM Bar l WHERE b.active = true AND b.foo = :foo之类的DQL查询似乎是解决方案,但是这样的查询将不会检测在调用EntityManager #flush()之前对Bar进行的任何未完成的更改(因为执行了DQL)反对数据库)。

1 个答案:

答案 0 :(得分:3)

这可能不是世界末日。如果加载Foo :: bars,已被修改,并且尚未提交回数据库,则唯一的选择是迭代。

如果没有加载Foo :: bars,那么它肯定没有被修改过,所以你也可以查询数据库。

(最后,如果已经加载,修改和提交了条形图,条形图集合的大小将决定是否更好地获取或迭代)

这让我感到好奇的是,实体有办法判断某个集合的成员是否已加载。

documentation似乎意味着Proxied ArrayCollection(在您的示例中为Foo:bars)将通过instanceof ArrayCollection测试。因此,您可能会尝试变得如此聪明:

     class Foo {   
       public function getActiveBars(){
         if ($this->bars instanceof \Doctrine\Common\Collection\ArrayCollection){
           //get active bars by iterating over $this->bars
         }else{
           //get active bars by DQL, and avoid loading $this->bars (for now).
         }
       }
     }