Переполнение стека в спящем режиме, вызванное отношением один ко многим - PullRequest
0 голосов
/ 07 февраля 2019

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

Игроку Сущности

@Entity
@Data
public class Player {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "player_id", updatable = false, unique = true, nullable = false)
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "num")
    private int num;
    @Column(name = "position")
    private String position;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
}

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

@Entity
@Data
public class Team {
    @Id
    @Column(name="team_id", updatable = false, unique = true)
    private String id;
    @Column(name = "name")
    private String name;
    @OneToMany(mappedBy = "team")
    private List<Player> players;
}

Мой репозиторий игрока

@Repository
public interface PlayerRepository extends CrudRepository<Player, Long> {
    Optional<Player> findById(Long id);
}

Записи базы данных в import.sql

insert into Team (team_id,name) values('Barcelona','Barcelona');
insert into Player (name,num,position,team_id) values('Andreas Inniesta', 8, 'Midfielder', 'Barcelona');
insert into Player (name,num,position,team_id) values('Lionel Messi', 10, 'Forward', 'Barcelona');

Таблица игроков на h2-console enter image description here

Это исключение

java.lang.StackOverflowError: null
        at java.lang.StringBuilder.append(StringBuilder.java:136) ~[na:1.8.0_121]
        at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
        at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
        at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
        at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
        at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
        at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
        at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
        at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
        at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
        at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
        at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
        at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]

Корень исключения

at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]

Более того, отладка ошибки показывает, что в объединенном столбце происходит сбой внутреннего преобразования в строку.enter image description here

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Как я вижу, вы используете Lombok.

Вы думаете, что не создаете toString метод, но Lombok так не считает.Аннотация @Data вызывает генерацию метода toString.

Из документации Lombok:

@Data - это удобная сокращенная аннотация, которая объединяет функции @ToString, @EqualsAndHashCode, @Getter / @Setter и @RequiredArgsConstructor вместе: Другими словами, @Data генерирует весь шаблон, который обычно ассоциируется с простыми POJO (Plain Old Java Objects) и bean: getters для всех полей,сеттеры для всех не финальных полей и соответствующих toString, реализаций equals и hashCode, которые включают в себя поля класса, и конструктор, который инициализирует все конечные поля, а также все не финальные поля без инициализатора, помеченные @NonNull, чтобы гарантировать, что поле никогда не будет нулевым.

Итак, Lombok создал toString метод для вас, который ведет к бесконечной рекурсии.

Вы можете исправить это с помощью::

@ToString(exclude = "players")
public class Team {
   // ...
}

Или:

@ToString(exclude = "players")
public class Team {
    @OneToMany(mappedBy = "team")
    @ToString.Exclude
    private List<Player> players;
}

Стоит упомянуть, если вам все еще нужно включить players в представление Team toString, попробуйте разобрать @Data аннотации и добавляйте только те части, которые вам действительно нужны.Затем определите свой собственный метод toString.

0 голосов
/ 07 февраля 2019

Это происходит потому, что когда вы хотите запросить команду, скажем, команду «А», она также содержит список игроков, входящих в команду «А», которые сами несут команду, в которой они находятся (команда «А»), который также несет список игроков ... Вы понимаете, это бесконечно циклически перебирает эти отношения без конца.Чтобы избежать ошибки StackOverflow, необходимо аннотировать сторону @OneToMany с помощью @JsonIgnore, если вы используете Jackson, или @JsonbTransient, если вы используете обычный jsonb.

@OneToMany(mappedBy = "team")
@JsonIgnore
private List<Player> players;

ИЛИ

@OneToMany(mappedBy = "team")
@JsonbTransient
private List<Player> players;

Таким образом, при запросе команды список игроков будет игнорироваться, и вы избежите ошибки.

...