Как остановить Hibernate от нетерпеливого извлечения многозначного связанного объекта

У меня есть свойство для объекта домена, объявленного в элементе "много-к-одному". Основной синтаксис этого свойства выглядит следующим образом:

<many-to-one name="propertyName" class="propertyClass" fetch="select" not-found="ignore" lazy="proxy" />

Теперь идея состоит в том, чтобы Hibernate НЕ охотно извлекал это свойство. Он может быть нулевым, поэтому установлен неверный указатель.

Но, Hibernate, после загрузки класса, содержащего эту ассоциацию, берет на себя загрузку фактического экземпляра класса (даже не прокси) при загрузке родительского класса. Поскольку некоторые свойства имеют размер более 1 МБ, они занимают много места кучи.

Если, однако, not-found установлен в исключение (или по умолчанию исключение), родительские классы, которые имеют это свойство, загружают прокси!

Как я могу остановить спящий режим, не загружая прокси-сервер, сохраняя при этом это свойство равным нулю?

Я нашел lazy = no-proxy, но в документации говорится о какой-то модификации байт-кода и не вдаваясь в подробности. Может кто-нибудь помочь мне?

Если это имеет значение, это версия Hibernate для Java, и это, по крайней мере, версия 3 (я могу посмотреть фактическую версию, если это помогает, но сейчас Hibernate 3+).

Я не указывал ранее, но версия Java 1.4. Таким образом, аннотации Java не поддерживаются.

Ответ 1

Если другой конец ассоциации может быть нулевым, я считаю, что hibernate должен запросить конец ассоциации, чтобы определить, должен ли он использовать прокси-сервер или нет (нет необходимости прокси-сервера, если другой конец равен нулю). Я не могу найти ссылку на это прямо сейчас, но я помню, как он где-то читал.

Для обеспечения ленивой загрузки полей документация относится к усовершенствованиям байт-кода в полях во время сборки: Использование lazy fetching свойства. Вот выдержка:

Hibernate3 поддерживает ленивый выбор индивидуальных свойств. Эта также известен метод оптимизации как группы выбора. Обратите внимание, что это в основном является маркетинговой функцией, как в практика, оптимизация чтения строк важнее оптимизации чтение столбцов. Однако только загрузка некоторые свойства класса могут быть полезно в крайних случаях, когда таблицы содержат сотни столбцов и модель данных не может быть улучшена.

Для загрузки Lazy встроенный байт-код инструментария! Если ваши постоянные классы не расширенный, Hibernate будет молча игнорировать ленивые настройки свойств и падать назад к немедленной выборке.

Ответ 2

Я нашел lazy = no-proxy, но документация рассказывает о каком-то байт-код и не идет в любые подробности. Кто-нибудь может мне помочь вне дома?

Предполагаю, что вы используете ANT для создания своего проекта.

<property name="src" value="/your/src/directory"/><!-- path of the source files -->
<property name="libs" value="/your/libs/directory"/><!-- path of your libraries -->
<property name="destination" value="/your/build/directory"/><!-- path of your build directory -->

<fileset id="applibs" dir="${libs}">
  <include name="hibernate3.jar" />
  <!-- include any other libraries you'll need here -->
</fileset>

<target name="compile">
  <javac srcdir="${src}" destdir="${destination}" debug="yes">
    <classpath>
      <fileset refid="applibs"/>
    </classpath>
  </javac>
</target>

<target name="instrument" depends="compile">
  <taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
    <classpath>
      <fileset refid="applibs"/>
    </classpath>
  </taskdef>

  <instrument verbose="true">
    <fileset dir="${destination}">
      <!-- substitute the package where you keep your domain objs -->
      <include name="/com/mycompany/domainobjects/*.class"/>
    </fileset>
  </instrument>
</target>

Ответ 3

Убедитесь, что ваш класс не является окончательным!

Ответ 4

Если вы передаете объект спящего режима из модели в представление через контроллер, не делайте этого!

Вместо этого сделайте "объект моментального снимка", чтобы сохранить значения из объекта Hibernate, который вы хотите передать в представление, и отображаться.

Почему? Прокси-сервер по-прежнему может извлекать значения, когда он находится в контроллере... но когда вы передаете прокси/объект в представление, он больше не может извлекать значения, потому что транзакция уже завершена. И вот почему я предложил то, что у меня было выше.

Ответ 5

При использовании аннотаций Hibernate, помещая @ManyToOne (fetch = FetchType.LAZY) в ассоциацию, выполняет то, что вы хотите. Вы пытались настроить fetch = "lazy", чтобы увидеть, работает ли это?

Ответ 6

@Мигель Пинг: Я думаю, что страница, на которую вы ссылаетесь, это [http://www.hibernate.org/162.html]. Насколько я понимаю, дополнительный SELECT необходим в случае стороны "один-к-одному", где внешнего ключа нет. Установка constrained="true" сообщает Hibernate, что другая сторона всегда присутствует и не требуется дополнительный SELECT.

Итак, для стороны "много-к-одному", где находится внешний ключ, не обязательно выполните другой SELECT, так как значение FK указывает, присутствует ли другой конец или null. По крайней мере, так я это понимаю.

До сих пор для теории. Прокси работает для меня на внешнем ключом/много-к-одному. Используемое сопоставление для ассоциации:

<many-to-one name="haendler" column="VERK_HAENDLOID" lazy="proxy" />

Но проксирование не работает для меня на стороне один к одному, используя сопоставление, подобное тому, которое описано в данном URL (constrained="true"). Хм, думаю, я открою для этого вопрос.; -)