Spring Boot, многие к одному, выбирают LAZY или EAGER - PullRequest
0 голосов
/ 20 июня 2019

Два объекта с двунаправленным отношением один ко многим.

Объект A указывает на список объектов B, которых будет не более нескольких.Объект B имеет обратную ссылку на A.

Когда он отображался как JSON, я ожидал увидеть A с числом B или B с соответствующим ему A. Но это, похоже, зависит от стратегии выборки в@OneToMany или @ManyToOne аннотация.

В большинстве прочитанных мной статей написано, что @ManyToOne должен быть LAZY, а @OneToMany - EAGER.И этот подход будет работать при перечислении объекта A;каждый A и связанные с ним буквы B показаны в формате JSON.

Но при перечислении B я получаю сообщение об ошибке

Ошибка определения типа: [простой тип, класс org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor];вложенным исключением является com.fasterxml.jackson.databind.exc.InvalidDefinitionException: не найден сериализатор для класса org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor и не обнаружено никаких свойств для создания BeanSerializer (чтобы избежать исключения, отключите SerializationFeature.FAIL_ONEANSP

Изменение LAZY на EAGER решает проблему. Но, с LAZY, я бы ожидал, что он по крайней мере вызовет записи B. Ошибка удивительна.

Я просто добавлю, чтов обоих определениях сущностей используется JsonIdentityInfo (добавлено для предотвращения бесконечной рекурсии), в котором используется SimpleObjectIdResolver.

Итак, в общем, я запутался. Я могу заставить его работать, но не совсем уверен, почему.

1 Ответ

0 голосов
/ 20 июня 2019

Большинство вещей, которые я прочитал, говорят, что @ManyToOne должно быть LAZY, а @OneToMany должно быть EAGER. И этот подход будет работать при перечислении объекта A; каждый A и связанные с ним буквы B показаны в формате JSON.

Это не то, что должно быть сделано, но по умолчанию. Это можно увидеть в документах @ManyToOne - и @OneToMany. Что должно быть сделано, зависит от варианта использования.


Исключение: если отношение определяется с отложенной загрузкой, вставляется прокси-объект, а реальная сущность выбирается из базы данных при необходимости. Джексон пытается сериализовать прокси и терпит неудачу. Это намекает на более глубокий архитектурный недостаток проекта: почему вы пытаетесь сериализовать объект базы данных? Между базой данных и процессом сериализации должен быть хотя бы один уровень (например, путем преобразования DTO).

Даже если сериализация будет работать должным образом (т. Е. Извлекается отсутствующий объект), наиболее вероятно, что транзакция, с которой был загружен объект, уже закрыта, и процесс приведет к LazyInitializationException. Если вы заранее знаете, что вам всегда нужно получить отношение, сделайте это с нетерпением. Если вам нужно только извлечь отношения в определенных случаях, закодируйте выборку в JPQL, CriteriaQuery, если необходимо, в собственном запросе. Извлечение лениво загруженного отношения @OneToMany приведет к проблеме N + 1 , которую следует избегать любой ценой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...