Hibernate 2 -й уровень кэша кеша, которые ленивы = false, приводят к поэмплэк = присоединение, это задокументировано где -нибудь?
-
21-09-2019 - |
Вопрос
Я испытываю следующую, по -видимому, недокументированную проблему, и я хочу понять, если
- Я сделал что -то не так
- Кто -нибудь столкнулся с той же проблемой?
- Это действительно нигде не задокументировано? Или я что -то пропустил?
Поведение - это предполагает следующее отображение
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Во -первых, в качестве фона значения по умолчанию Hibernate для принести Атрибут на отношение для многих к одному должно быть »Выбрать", Это, по крайней мере, то, что задокументировано (я добавлю ссылку здесь, когда найду ее)
Тем не менее, это, по -видимому, верно только в том случае, если ссылочный класс ленивый = "true"!
По -видимому, вышеупомянутое отображение переводится в это (потому что бар ленивый = "false"):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Теперь почему это будет проблемой? Вместо 2 выбора Hibernate загрузит не ленивую ссылку в один выбор с его «родителем» (загрузите Foo с помощью стержня в одном выборе)
Это на самом деле имеет смысл, поскольку объект не ленив, почему бы не загрузить его?
Ответ такого: что происходит, если бар находится во втором уровне кэша?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
И ответ на это - ничего не меняется!
По -видимому, можно предположить, что Hibernate достаточно умный, чтобы понять, что объекты этого типа не должны загружаться, но поскольку выборочная выборка по умолчанию была изменена с Select на Join, у Hibernate нет выбора (вы не можете присоединиться к реальной таблице с Кэш 2 -го уровня, пока)
Таким образом, Hibernate делает то, что ему говорят, и использует соединение, чтобы принести объект из базы данных, где он уже находится во 2 -м кэше
Решение, которое я обнаружил, заключается в том, чтобы буквально изменить отображение на fetch = "select"
Теперь, когда второй выбор для бара собирается пойти, Hibernate понимает, что он не должен идти в базу данных, и извлекать его из кэша. и только 1 запрос будет выполнен (после разминки)
Решение
Я столкнулся с той же проблемой и обнаружил, что отмечаю все отношения, которые будут кэшированы как fetch="select"
. Анкет В то время, когда запрашивается запрос, Hibernate не может знать, находится ли запрашиваемый экземпляр Bar в кэше второго уровня или нет (при условии, что Foo не в кэшировании).