Как справиться с самоопределением в Spring Data JPA с Spring Boot 2? - PullRequest
1 голос
/ 28 января 2020

У меня есть приложение Spring Boot 2, в котором у меня есть следующая сущность пользователя:

@Data
... JPA and other annotations
class User {
    ... many fields including Integer id
    @ManyToOne(fetch = FetchType.LAZY)
    public User createBy;
    @ManyToOne(fetch = FetchType.LAZY)
    public User updateBy;
}

Теперь главная проблема, с которой я сейчас сталкиваюсь, - это ссылка на пользователя (от пользователя) и это либо вызывает исключения StackOverflow, либо InvalidDefinitionException в зависимости от определенных аннотаций, которые я использую для пользователя. Эта проблема очень распространена, и в inte rnet обсуждается несколько решений:

1. Аннотируйте оба поля с помощью @ JsonBackReference При аннотировании с помощью @JsonBackReference поля updateBy и createBy вообще опускаются, то есть я не получаю их при желании в своих ответах API.

2. Класс аннотации с @JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") или None.class или IntSequenceGenerator.class или UUIDGenerator.class Этот подход работает, пока сериализатор не найдет тот же пользовательский объект где-нибудь вниз json и вместо того, чтобы поместить его туда снова, он помещает ссылку на этот объект на основе класса, выбранного выше. например,

[
  {"id": 1, ..., "createBy": {"id": 2, ...},
  2 // <- Let's ignore how user 1 is created by user 2 and notice that instead of a user object, I get an integer ID reference.
]

Это означает, что клиент, анализирующий эти данные, часто будет объектом, а не числом, вызывая ошибки синтаксического анализа.

3. Реализация собственного сериализатора (или расширение существующего) Теперь я действительно не уверен, что это правильный путь к go в достижении моих целей (упомянутых ниже). Но если это правильный подход, как бы я go справился с этой самореференцией?

ЦЕЛИ:

  1. Сериализовать данные так, чтобы по крайней мере определенные поля в дочернем объекте (пользователь) передаются обратно, предотвращая дальнейшие рекурсивные вызовы.
{
  "id": 1, "name": "old user", .. many other fields .., "createBy": {id: 2, "name": "2nd user"}
}
Когда клиент отправляет объект пользователя как тело запроса, приложению требуется только идентификатор дочернего объекта, а не весь объект, как показано ниже:
{
   "name": "new user", ...., "createBy": {id: 1}
}

Я знаю, что самообслуживание ссылка является неотъемлемой частью ORM, и существует множество вариантов использования для самостоятельной ссылки. Но как профессиональные разработчики / приложения решают эту проблему, особенно в Spring Framework? Если пользовательский сериализатор является единственным способом go, как мне заставить его функционировать надлежащим образом?

Кроме того, желательно ли исключить эти поля (createBy и updateBy) из методов EqualsAndHashCode и ToString?

...