2011-01-26 2 views
9

У меня проблема, когда JPA пытается лениво загрузить мои данные, когда я этого не хочу. По сути дела, я использую Сервис для извлечения некоторых данных, и когда я перехожу к анализу этих данных в JSON, библиотека JSON запускает спящий режим, чтобы попытаться лениво загрузить данные. Есть ли способ остановить это? Я привел пример ниже.JPA2/Hibernate - остановить ленивую загрузку?

// Web Controller method 
public String getEmployeesByQuery(String query) { 

    Gson gson = new Gson(); 
    List<Employee> employees = employeeService.findEmployeesByQuery(query); 

    // Here is where the problem is occurring - the gson.toJSON() method is (I imagine) 
    // using my getters to format the JSON output, which is triggering hibernate to 
    // try and lazily load my data... 
    return gson.toJSON(employees); 
} 

Возможно ли установить JPA/hibernate, чтобы не пытаться и лениво загружать данные?

UPDATE: Я понимаю, что вы можете использовать FetchType.EAGER - но что, если я не хочу загружать эти данные? Я просто хочу остановить спящий режим от попытки получить больше данных - у меня уже есть данные, которые я хочу. Прямо сейчас, когда я пытаюсь получить доступ к методу get(), hibernate вызовет ошибку «no session или session is closed», что имеет смысл, поскольку моя транзакция уже была совершена с моей службы.

Спасибо!

+0

Не могли бы вы рассказать подробнее о своем вопросе: хотите ли вы полностью переключиться с ленивой загрузки на желаемую загрузку или не хотите ленивать загрузку сотрудников в этом конкретном случае и почему. – gabuzo

+0

Моя проблема в том, что я не хочу лениво загружать данные. Конечно, я мог бы отметить это для загрузки EAGER - но что, если я сейчас даже не забочусь об этих данных? Например, если у меня есть Сотрудник, у которого много позиций, но я не хочу этих данных, потому что он слишком подробен для представления, которое я хочу отобразить, как я могу сказать, что JPA не пытается и не извлекает эти данные? –

+0

Попробуйте это: http://stackoverflow.com/questions/4802887/gson-how-to-exclude-specific-fields-from-serialization-without-annotations –

ответ

3

Вы действительно есть два варианта:

  1. Вы можете скопировать данные от сотрудника одного, который не проксируемый на спящем режиме.
  2. Посмотрите, есть ли способ, чтобы библиотека toJSON не отражала весь график объекта.Я знаю, что некоторые библиотеки JSON позволяют вам сериализовать некоторые свойства объекта JSON.

Лично я думал бы, что # 1 будет проще, если в вашей библиотеке используется только отражение.

+0

Похоже, что это могут быть единственные варианты. Но ни один из них не идеален. Вы бы подумали, что JPA будет указывать способ, чтобы отдельные элементы не пытались получить больше данных ... –

+0

Я использовал hibernate и JPA и имел эту проблему в обоих. Я никогда не находил хороший способ решить эту проблему. – Ruggs

0

Вы всегда можете изменить атрибут fetch к FetchType.EAGER, но это также стоит обратить внимание, если у вас есть ваши сделки имеют право сферы. Коллекции будут правильно загружены, если они будут доступны в транзакции.

6

Есть несколько вариантов:

  • Если вы всегда необходимо загрузить свою коллекцию с нетерпением, вы можете указать fetch = FetchType.EAGER в вашем отображении, как это было предложено в других ответах.

  • В противном случае вы можете включить нетерпеливый выборки для конкретного запроса:

    • Используя JOIN FETCH пункт в HQL/JPQL запроса:

      SELECT e FROM Employee e JOIN FETCH e.children WHERE ... 
      
    • Используя fetch profiles (в JPA вы можете получить доступ к Hibernate Session с использованием em.unwrap(Session.class))
+0

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

+0

@Brian: Если вы не хотите включать эти поля в представление JSON, вы должны проинструктировать ваш сериализатор JSON игнорировать эти поля, как это было предложено Ruggs. Это не имеет ничего общего с JPA и Hibernate. – axtavt

1

Предлагаю вам сделать полученную копию копий объектов, которые вы хотите использовать за пределами транзакции. Таким образом, ленивая загрузка произойдет изнутри транзакции, и вы можете передать Gson простой, а не расширенный POJO.

Вы можете использовать Doozer для этого. Он очень гибкий и с небольшой настройкой (читайте , вы потеряете свои волосы, настроив его на), вы даже можете получить только частично данные, которые хотите отправить в Gson.

+0

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

+0

Вы можете сделать это вручную, если хотите использовать рефлексивность для поиска геттеров и сеттеров, но используя библиотеку, вы сэкономите время на разработку скучной ошибки. – gabuzo

0

Ваша проблема в том, что вы сериализуете данные. Мы столкнулись с такой же проблемой с Flex и JPA/Hibernate. Трюк в зависимости от того, сколько вы хотите калечить,

  1. Измените вашу модель данных, чтобы не гоняться за теми данными, которые вы не хотите.
  2. Скопируйте данные, которые вы хотите в какой-то DTO, у которых нет отношений, о которых можно беспокоиться.
  3. Предполагая, что вы используете Hibernate, добавьте фильтр Session-in-view .... что-то вроде этого, он будет держать сеанс открытым во время сериализации всей базы данных. ;)

Первый вариант - это то, что мы сделали для первого крупного проекта, который мы сделали, но он испортил библиотеку доступа к данным, которую мы использовали для любого вида использования общего назначения. С тех пор мы больше ориентировались на второй вариант.

YMMV

2

Как уже говорилось, это не проблема с JPA/спящий режим, а с библиотекой JSON сериализации вы используете. Вы должны instruct gson, чтобы исключить свойства, которые вы не хотите пройти.

0

Простая и простая задача - создать новые классы данных (что-то вроде DTO). Используйте Hibernate.isInitialized(), чтобы проверить, инициализирован ли объект спящим или нет. Я проверяю gson, могу ли я что-то переопределить. Я отправлю его здесь, если найду что-нибудь новое.

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