Представьте, что у вас есть две таблицы, А и Б. Есть связка между ними.
И вот вы пишете запрос (через O/RM) к этим таблицам:
select a.* from A a
inner join B b on a.field1 = b.field2
where b.field3 = 42
Тут запрос показан на SQL, но это просто чтобы понятно было. А написали вы
его средствами своей O/RM.
Предположим, что у вас в базе хранятся следующие объекты:
a1, a2; b1, b2, b3.
Ваш запрос из БД вернет следующее: a1, a2 (a[i] джойнится с b[i]).
У всех нормальных O/RM есть локальное хранилище объектов. Будем называть его
кэш, хотя в нем хранятся еще новые объекты, например. На начало работы программы
он пустой.
После первого запроса, в кэше будут лежать следующие объекты:
Сache: a1, a2.
Db: a1, a2; b1, b2, b3.
У всех нормальных O/RM можно указать стратегию выбора сущностей. К примеру
DatabaseOnly, CacheOnly, DatabaseThenCache.
Обычно все стараются не заморачиваться, и ставить DatabaseThenCache. Это
значит, что в ходе запроса сущности будут выбираться как из базы данных, так и
из кэша. Особенно это актуально, когда надо выполнить запрос, а в кэше есть еще
не сохраненные сущности.
Допустим, что вы создали сущность a3, которая должна джойнится с b3 и
попадать в результаты запроса. Эта сущность еще не сохранена в БД и находится
только в локальном кэше, то есть состояние такое:
Сache: a1, a2, a3.
Db: a1, a2; b1, b2, b3.
Выполняем наш запрос, который по идее должен вернуть все три сущности. Что он
возвратит? Правильно, он вернет только a1 и a2.
Сколько раз уж натыкался на эти грабли, а все бесит.