Остановка рекурсии из двунаправленных взаимно однозначных сопоставлений

#spring #hibernate

#пружинная #спящий режим

Вопрос:

У меня есть объект UserProfile, который содержит ссылку на объект TwitchAccount через отношение один к одному, как показано здесь:

TwitchAccount.java:

 @OneToOne(mappedBy = "twitchAccount")
private UserProfile profile;
  

UserProfile.java:

 @OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "twitchAccountId", referencedColumnName = "twitchAccountId")
private TwitchAccount twitchAccount;
  

Когда я выполняю запрос GET для определенного объекта TwitchAccount, кажется, что между ними происходит рекурсия, как видно:

 {"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":{"id":8,"firstName":null,"lastName":null,"profilePicUrl":null,"birthday":null,"steamId":null,"xblId":null,"psnId":null,"epicId":null,"discordId":null,"twitchAccount":{"id":1,"state":"525367bb-ca4c-4131-ac52-e29aafdb7dc1","code":null,"userProfile":
  

Как я могу остановить эту рекурсию и как я могу сделать так, чтобы учетная запись twitch даже не возвращала json, связанный с объектом профиля пользователя (объект учетной записи twitch не должен иметь возможности устанавливать или получать userprofile в любом случае)?

Комментарии:

1. Не могли бы вы опубликовать некоторый код из сервиса, в котором вы конвертируете модели в DTO?

2. @ChristosK. я просто возвращал сами модели. это плохо?

3. Это зависит от того, есть ли какие-либо данные, которые пользователь не должен видеть, разве в таблице учетных записей нет поля пароля? Вы используете какую-то аннотацию JsonIgnore? Тем не менее, лучше преобразовать в пользовательский класс, не являющийся сущностью, прежде чем использовать контроллер REST. Не могли бы вы опубликовать все объекты TwitchAcount и UserProfile для рекурсии сейчас?

4. Кроме того, когда вы делаете этот запрос GET, чтобы получить TwitchAccount, нужно ли вам также получать с ним профиль пользователя? Вы должны четко указать, в чем именно заключается ваша цель

5. @ChristosK. не хотите, чтобы он содержал профиль пользователя. я полагаю, что вы дали мне решение: используйте dto, который не содержит profile

Ответ №1:

Вы могли бы просто аннотировать profile свойство с помощью @JsonIgnore, например,

 @JsonIgnore
@OneToOne(mappedBy = "twitchAccount")
private UserProfile profile;
  

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

Итак, создайте DTO для обоих объектов, а в их соответствующих службах создайте методы преобразования, и все готово, вы контролируете то, что вы установили.


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

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