Хороший вопрос: Вы должны сделать немного больше «глубокого погружения», чтобы понять, что происходит. В данном случае это не вопрос дизайна REST. Я не знаю, были ли вы удивлены, увидев актерский состав с информацией о фильме, но вы должны были это сделать.
Ваш код return repository.findById(id) …
явно предназначен для извлечения только информации о фильме, но вы заметили, что также получаете актерский состав. Вы печатали операторы sql из системы Spring Data Jpa
, чтобы увидеть, работает ли она так, как вы ожидали? Я подозреваю, что нет, потому что если бы вы имели, вы, вероятно, заметили бы, что несколько операторов SQL генерируются. Сначала для фильма, а потом и для актеров.
Как только вы проследите, почему вы получаете несколько SQL-операторов, вы обнаружите, что эти операторы исходят из преобразования Entity-> JSON. Это означает, что когда ваш сервис возвращает сущность Movie
, среда Spring должна преобразовать ее в JSON для отправки по проводам, и этот код проходит по графу объектов. Граф объектов - это экземпляры сущностей, которые вы создали в JVM, когда запрашивали базу данных. Поскольку вы сопоставили отношение Movie/Cast
, объект фильма включает в себя возможные ссылки на приведение, и когда код преобразования JSON выполняет выборку для свойства преобразования, JPA обнаруживает, что выдает другой запрос, поскольку среда Spring по-прежнему удерживает транзакцию базы данных в области видимости. Если бы транзакция была вне контекста, вы бы получили исключение LazyInitialization
. Все это вы должны исследовать немного больше, чтобы вы поняли это.
Итак, как вам сделать лучший дизайн? У вас есть как минимум две возможности, которые приходят на ум. Во-первых, вы можете удалить отображение cast
. Как вы думаете, зачем вам нужна коллекция cast
в фильме? Если вы хотите получить актерский состав для фильма, вы можете просто позвонить castRepository.findByMovie(movie)
и получить список. Во-вторых, вы можете использовать DTO или Data Transfer Object, который представляет собой отдельный POJO, который определяет, что вы хотите, чтобы ваш интерфейс REST действительно возвращал. В этом случае это может быть класс MovieDto
, который совпадает с классом сущности Movie
, но без свойства cast. Затем вы изменили бы свой movieRepository
на метод, определенный как Optional<MovieDto> findById(Long id)
, и spring-data-jpa будет использовать функцию Проекции для автоматического преобразования вашего объекта Movie
в объект MovieDto
.
Использование функции Проекции будет моим рекомендуемым подходом. DTO предназначены для «представлений» бизнес-уровня вашего приложения. Разные потребители вашего сервиса могут хотеть разных взглядов на мир кино. Агентам по кастингу может потребоваться список всех фильмов, в которых появился актер, в то время как кинокритики могут захотеть получить список актеров, а любителям кино и кино может просто потребоваться информация о фильме. Все разные DTO или представления для одной и той же базы данных. Я также внимательно рассмотрю вопрос о том, действительно ли вам нужно отображение cast
. Я заметил, что у вас есть сегмент кода cast = new HashMap<>();
, который создает HashMap
для стороны фильма, но вам это не нужно, и в типичном случае чтения он будет выброшен, что приведет к нагрузке на сборщик мусора. Наконец я заметил, что вы определили приведение как карту, но почему вы это сделали? Что происходит в ключе карты, в названии фильма? Это плохой дизайн. Актеры могут появляться в более чем одном фильме, а фильмы могут иметь более одного актера, поэтому у вас должно быть отношение «многие ко многим».
Наконец, вот почему в SO так не одобряются вопросы "это хороший дизайн". Ответы сложны и, как правило, самоуверенны, а не для чего предназначен SO.