2

Я новичок в JEE и недавно начал изучать Spring и Hibernate. Я пытаюсь разработать службу RESTful для отслеживания элементов с категориями. У меня есть ассоциация «многие-ко-многим» (один элемент может иметь много категорий, а одна категория может иметь много элементов), три таблицы: элемент, категория и таблица соединений item_category.Hibernate много-много ленивое исключение инициализации

Я использую сервер MySQL, Spring загрузки 1.3.1 и Hibernate 4.3

То, что я хочу сделать прямо сейчас, чтобы получить список элементов с категориями и категориями со списком элементов. Я написал для него все приложение с API и закончил с LazyInitializationException. Я пробовал много подходов, но это не помогло. (Я могу настроить тип EACHER, но это не решение).

, например, это API, чтобы перечислить все пункты: GET /api/item

и это выход: (! Не ожидается):

Вызванный: org.hibernate.LazyInitializationException: не удалось лениво> инициализировать коллекцию роли: com.sk.itemlist.domain.Item.categories, не удалось инициализировать прокси - нет сеанса на org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException (AbstractPersistentCollection.java:575) ~ [hibernate-core -4.3.10.Final.jar: 4.3.10.Финал] на org.hibernate.collection.int ernal.AbstractPersistentCollection.withTemporarySessionIfNeeded (AbstractPersistentCollection.java:214) ~ [hibernate-core-4.3.10.Final.jar: 4.3.10.Final] at org.hibernate.collection.internal.AbstractPersistentCollection.readSize (AbstractPersistentCollection.java: 155) ~ [hibernate-core-4.3.10.Final.jar: 4.3.10.Final] at org.hibernate.collection.internal.PersistentSet.size (PersistentSet.java:160) ~ [hibernate-core-4.3. 10.Final.jar: 4.3.10.Final] at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize (CollectionSerializer.java:101) ~ [jackson-databind-2.6.5.jar: 2.6. 5] at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize (CollectionSerializer.java:24) ~ [jackson-databind-2.6.5.jar: 2.6.5] at com.fasterxml.jackson. databind.ser.BeanPropertyWriter.serializeAsField (BeanPropertyWriter.java:693) ~ [jackson-da tabind-2.6.5.jar: 2.6.5] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields (BeanSerializerBase.java:675) ~ [jackson-databind-2.6.5.jar: 2.6. 5]

же ошибка, если вы пытаетесь получить все категории GET /api/category или категории по идентификатору GET /api/category/1

Так вот мои вопросы:

  1. Как избавиться от LazyInitializationException? Как настроить hibernate для повторного открытия сеанса? Или я должен инициализировать сбор в слое DAO?
  2. Я читал о шаблоне DTO, я не совсем понимаю, что это такое, если я буду копать глубже здесь?
  3. Я заметил проблему, когда пытаюсь вставить данные в элементы. Он вставляет только в таблицу элементов, таблица соединений и категория пусты. Я вручную добавил данные в БД для тестирования
  4. Что вы думаете обо всем приложении? Что можно улучшить здесь или то, что следует избегать (если таковые имеются)

И, наконец, я загрузил полный проект здесь: https://gitlab.com/sksh/ItemList.git
В ресурсах вы можете найти дамп базы данных с некоторыми случайными данными.Обновите application.properties с действительными учетными данными db.

+0

является 'public Category findByKey (String key)' в 'CategoryDaoImpl.java' метод, который вы пытаетесь назвать, который дает вам это исключение? –

+0

@Rdx он бросает его везде, findById, listAll и т. Д. Он начал бросать, так как я добавил список элементов в категории. – costello

+0

GET/api/category throws org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию роли: com.sk.itemlist.domain.Category.items, не удалось инициализировать прокси - нет сеанса и наоборот, если я попытаюсь извлечь все (GET/api/item), но в этом случае он не может инициализировать категории – costello

ответ

1

Что происходит:

  • Вы спрашиваете зимуют принести некоторые пункты
  • Hibernate приносит их, но не приносит информации категорий элемента.
  • Когда вы пытаетесь получить доступ к этим категориям после завершения работы сеанса DB (в CollectionSerializer), вы получаете это исключение
  • Вам нужно попросить спящий режим вместе с элементами, чтобы привести категории вместе, чтобы вы могли для использования (итерации, списка или других) после окончания сеанса.

Вы должны использовать что-то вроде уровня DAO ..

// fetch a Criteria reference and use join fetching 
Criteria c = currentSession().createCriteria(Item.class); 
c.setFetchMode("categories", FetchMode.JOIN); 
c.add(Restrictions.eq("id", id)); 
Item result = (Item)c.uniqueResult(); 
return result;  

Есть и другие способы, как объявить в пункте

@ManyToMany(fetch=FetchType.EAGER) 
private Set<Category> categories = new HashSet<>(); 

, но это может привести к выполнению вопросы

+0

Я изменил метод findById в ItemDaoImpl, используя ваше предложение, и теперь получаю новое исключение: 'org.springframework.http.converter.HttpMessageNotWritableException: Could не писать содержимое: не удалось лениво инициализировать коллекцию роли: com.sk.itemlist.domain.Category.items, не удалось инициализировать прокси - нет сеанса (через цепочку ссылок: com.sk.itemlist.domain.Item ["categories" ] -> org.hibernate.collection.internal.PersistentSet [0] -> com.sk.itemlist.domain.Category ["itemList"]); ' – costello

+1

Теперь у вас такая же проблема в категории perspe ctive. Ваш сериализатор попытается написать список элементов. Каждый элемент имеет список категорий. У каждой категории есть список предметов. И так далее. Вам нужно решить, где отрезать ссылки, получаемые в вашем представлении. И Джексон не будет делать это автоматически, вы должны сделать некоторую реализацию. Что я обычно делаю: я реализую себе информацию, которая должна быть возвращена в API, используя другой набор DTO, которые фактически сериализуются с помощью jackson, поэтому я контролирую, когда поле сбора должно быть доступно за пределами сеанса – yugo

+0

Так что я должен использовать объекты dto со всей необходимой информацией вместо объектов сущности? – costello