StackOverflowError: null в обеих сторонах - PullRequest
0 голосов
/ 16 марта 2020

Это первый раз, когда я сталкиваюсь с этой проблемой. У меня есть две сущности с взаимоотношениями @OneToMany и @ManyToOne.

Субъект команды:

@Entity
@Data
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String image;

    @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "team")
    private List<Player> playerList = new ArrayList<>();
}

Сущность игрока:

@Data
@Entity
public class Player {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nickname;

    @ManyToOne
    private Team team;
}

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

@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class PlayerController {
    private final PlayerRepository playerRepository;

    @GetMapping("/player")
    public List<Player> getPlayers() {
        return playerRepository.findAll();
    }
}

Я сталкиваюсь с java.lang.StackOverflowError: null:

2020-03-15 21:58:48.419  WARN 8576 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Failure while trying to resolve exception [org.springframework.http.converter.HttpMessageNotWritableException]

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
[...]

2020-03-15 21:58:48.423 ERROR 8576 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.gottaaimfast.website.model.Player["team"]->com.gottaaimfast.website.model.Team["playerList"]->org.hibernate.collection.internal.PersistentBag[0]->com.gottaaimfast.website.model.Player["team"]->com.gottaaimfast.website.model.Team["playerList"]->org.hibernate.collection.internal.PersistentBag[0]->com.gottaaimfast.website.model.Player["team"]->com.gottaaimfast.website.model.Team["playerList"]->org.hibernate.collection.internal.PersistentBag[0]->com.gottaaimfast.website.model.Player["team"]->com.gottaaimfast.website.model.Team["playerList"]->org.hibernate.collection.internal.PersistentBag[0]->com.gottaaimfast.website.model.Player["team"]->com.gottaaimfast.website.model.Team["playerList"]->org.hibernate.collection.internal.PersistentBag[0]->[...] with root cause

java.lang.StackOverflowError: null
    at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) ~[na:na]
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579) ~[na:na]
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
**AND IT LOOPS OVER AND OVER**

Кажется, что он сталкивается с каким-то l oop, но я понятия не имею, почему. Буду очень благодарен за любую помощь!

Ответы [ 2 ]

2 голосов
/ 16 марта 2020

эта двунаправленная json проблема с отображением добавляет эти аннотации к соответствующим полям ваших сущностей

В Игроке:

    @ManyToOne
    @JsonManagedReference
    private Team team;

В Команде:

    @JsonBackReference
    @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy ="team")
    private List<Player> playerList = new ArrayList<>();

Смотрите это ответ:

Предотвращение рекурсивной ассоциации в спящем режиме ManyToOne

1 голос
/ 16 марта 2020

Значение l oop связано с тем, что вы используете сериализацию по умолчанию для json. У вас двунаправленные отношения ManyToOne, поэтому:

  • Для каждого игрока вы хотите вывести свою команду
  • Для команды вы выводите игроков в команду

и, следовательно, у вас есть цикл в процессе сериализации.

Ваши варианты:

  • использовать @JsonIgnore на одной стороне отношения ManyToOne, чтобы разорвать цикл
  • использование пользовательского DTO Без циклов для передачи данных
  • Использование @JsonManagedReference и @JsonBackReference
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...