Skip to content

Возможно fetch="lazy" недостаточно lazy #2

Closed
@AlexeyDsov

Description

@AlexeyDsov

Постараюсь описать прецендент. Допустим у нас есть класс Actor у который связан через OneToOne с классом Film через propery 'bestFilm' и связь в таком случае fetch="lazy"

Приведу в пример следующий код (в коде транслит, т.к. там проблема с кодировкой):

<?php
$actor = Actor::dao()->getById(16); //Get some actor
$film = $actor->getBestFilm(); //get best film from actor (and film stay in actor now)
$filmId = $film->getId(); //get best film id
Film::dao()->uncacheLists();
//compare object:
print spl_object_hash($actor->getBestFilm())."\n";
print spl_object_hash(Film::dao()->getById($filmId))."\n";
?>

В результате у нас оказывается два разных экземпляра с одинаковым идентификатором, что может привести к путанице кода и коллизии.
В случае когда объект fetch cascade или join - автоматически уберечься от этого нельзя. Однако в случае lazy, от подобных прецендентов можно уберечься если в Actor не хранить ссылку на объект film, а хранить лишь идентификатор, а метод getBestFilm переписать на:

<?php
public function getBestFilm()
{
    if ($this->bestFilmId !== null) {
        return Film::dao()->getById($this->bestFilmId);
    }
    return null;
}
?>

При этом лишних запросов byId в базу не появиться, т.к. либо объект будет браться из identityMap либо кэша. А загружаться из базы будет лишь если кэш сброшен.


Плюсы: возможность избежать описанных выше коллизий и удерживания старых объектов в других объектах

Минусы: работа с объектами связанными по fetch="lazy" будет несколько отличаться от работы с объектами связанным join или cascade.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions