Description
Постараюсь описать прецендент. Допустим у нас есть класс 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.