2009-12-28 6 views
6

переживает следующий кажущийся недокументированный вопрос, и я хочу, чтобы понять, еслиСпящий режим 2-го уровня кэш-объекты, которые lazy = false, приводят к по умолчанию fetch = join, документированы ли они где-нибудь?

  1. я сделал что-то неправильно
  2. ли кто-нибудь столкнуться с таким же вопросом?
  3. Действительно ли это не документировано нигде? или я что-то пропустил?

Поведение это Предположим следующее отображение

<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 значение по умолчанию для выборки атрибут отношения многие-к-одному должна быть "выберите ", это, по крайней мере, то, что документировано (я добавлю ссылку здесь, когда найду его)

Однако это, по-видимому, верно только в том случае, если ссылочный класс lazy =" true "!

так очевидно выше отображение переводится на это (потому что Bar ленив = «ложь»):

<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 с помощью Bar в одном select)

Это действительно имеет смысл, поскольку объект не ленив, почему бы не загрузить Это?

Ответ таков: что произойдет, если Bar находится в кеше второго уровня?

<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 запрос будет выполнен (после разминки)

+0

Поведение выборки зависит от API, который вы используете для запроса объектов. Вы используете API HQL или Criteria? – skaffman

+0

Ни один простой session.load (Foo.class, id) –

ответ

4

Я столкнулся с той же проблемой и обнаружил, что отмечу все отношения «один-к-одному», которые будут кэшироваться как fetch="select". Во время создания запроса Hibernate не может знать, находится ли запрашиваемый экземпляр Bar во втором кеше второго уровня или нет (предполагается, что Foo не кэшируется).

+0

Но разве это не странно, что это не документировано, даже в официальных коммерческих книгах?Даже на форумах или здесь, в SO, я не нашел упоминаний об этой проблеме ... –

+0

Согласен. Но чтобы понять, что именно делает гибернация, мне часто приходится записывать данные в sql и смотреть, что происходит на самом деле. – bertolami

 Смежные вопросы

  • Нет связанных вопросов^_^