доктрина 2 - как обрабатывать несинхронизированные базы данных / сущности - PullRequest
2 голосов
/ 03 января 2011

Я работаю над веб-приложением PHP и надеюсь использовать Doctrine 2.0 для функциональности ORM.Однако у меня возникли значительные проблемы с одним конкретным типом запроса.

Рассмотрим простую модель домена, содержащую сущности Foo и Bar.Объект 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?1010 * Следующий код работает правильно, но производительность будет проблемой, если в базе данных много неактивных объектов Bar.Итерирование по коллекции Bar приводит к выполнению большого запроса к базе данных.

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

Выполнение запроса DQL, такого как SELECT b FROM Bar l WHERE b.active = true AND b.foo = :foo в getActiveBar (), кажется решением, однако такой запрос необнаруживать любые незавершенные изменения в Bar, сделанные до вызова EntityManager # flush () (поскольку DQL выполняется для базы данных).

1 Ответ

3 голосов
/ 04 января 2011

Это, вероятно, не конец света.Если Foo :: bars загружен, был изменен и не был передан обратно в базу данных, ваш единственный вариант - выполнить итерацию.

Если Foo :: bars не был загружен, то он, конечно, не был изменен, так что вы также можете запросить базу данных.

(Наконец, если бары были загружены,измененный и зафиксированный, размер коллекции баров будет решать, будет ли выборка или итерация лучше, вероятно)

Мне интересно, есть ли у сущности способ узнать, является ли член коллекциейбыл загружен или нет.

Документация , кажется, подразумевает, что 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).
         }
       }
     }
...