StackOverflowError возникает, когда я пытаюсь сделать запрос JPQL JOIN - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть следующие объекты:

@Data
@Entity
@Table(name = "artist")
public class Artist {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="artist_id")
    private int id;
    @Column(name="artist_name", length = 2000)
    private String name;
    private String country;
    @OneToMany(mappedBy = "artist", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Song> songs = new ArrayList<>();

    public Artist(String name, String country){
        this.name=name;
        this.country=country;
    }
}

@Data
@Entity
@Table(name = "songs")
public class Song {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int songId;
    @Column(name = "text", length = 65600)
    private String text;
    private Double rating;
    private String songName;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "artist_id", nullable = false)
    public Artist artist;

    public Song(String text, Double rating, String songName, Artist artist) {
        this.text = text;
        this.rating = rating;
        this.songName = songName;
        this.artist = artist;
    }
}

Я пытаюсь получить все песни по шаблону имени исполнителя:

@ Query ("ВЫБРАТЬ s ИЗ песни s, ГДЕ s.artist.name LIKE CONCAT ('%' ,: name, '%') ")
Список findByArtistsName (@Param (" name ") имя строки);

и всех исполнителей по песнямимя патерна:

@Query("SELECT a FROM Artist a JOIN FETCH a.songs s WHERE s.songName LIKE CONCAT('%',:pattern,'%')")
List<Artist> findBySong(@Param("pattern") String songName);

Для этого я использую JPQL-запросы соответственно.Но оба достали мне один и тот же StackOverflowError.

> 
> 
>     Caused by: java.lang.StackOverflowError: null
>       at sun.misc.FloatingDecimal$BinaryToASCIIBuffer.dtoa(FloatingDecimal.java:431)
> ~[na:1.8.0_151]
>       at sun.misc.FloatingDecimal$BinaryToASCIIBuffer.access$100(FloatingDecimal.java:259)
> ~[na:1.8.0_151]
>       at sun.misc.FloatingDecimal.getBinaryToASCIIConverter(FloatingDecimal.java:1785)
> ~[na:1.8.0_151]
>       at sun.misc.FloatingDecimal.getBinaryToASCIIConverter(FloatingDecimal.java:1738)
> ~[na:1.8.0_151]
>       at sun.misc.FloatingDecimal.toJavaFormatString(FloatingDecimal.java:70)
> ~[na:1.8.0_151]
>       at java.lang.Double.toString(Double.java:204) ~[na:1.8.0_151]
>       at java.lang.Double.toString(Double.java:644) ~[na:1.8.0_151]
>       at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_151]
>       at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_151]
>       at com.music.entity.Song.toString(Song.java:8) ~[classes/:na]
>       at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_151]
>       at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_151]
>       at java.util.AbstractCollection.toString(AbstractCollection.java:462)
> ~[na:1.8.0_151]
>       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_151]
>       at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_151]
>       at com.music.entity.Artist.toString(Artist.java:9) ~[classes/:na]
>       at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_151]
>       at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_151]
>       at com.music.entity.Song.toString(Song.java:8) ~[classes/:na]
>       at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_151]
>       at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_151]
>       at java.util.AbstractCollection.toString(AbstractCollection.java:462)
> ~[na:1.8.0_151]

Как правильно решить эту проблему?

1 Ответ

0 голосов
/ 24 сентября 2018

Это почти наверняка вызвано тем, что вы используете Lombok и аннотацию @Data, которая является ярлыком для других аннотаций Lombok:

@ ToString, @EqualsAndHashCode, @Getter для всех полей и @Setter для всех не финальных полей, и @ RequiredArgsConstructor

Аннотация @ToString автоматически генерирует метод toString, который включает в себя все ваши поля.Нижняя часть трассировки стека указывает на вызов метода toString в коллекции. Если вы проследите за стеком, вы сможете определить цикл, вызывающий переполнение стека:

AbstractCollection.toString -> Song.toString-> Artist.toString -> AbstractCollection.toString -> Song.toString ...

Ваша сущность Artist содержит коллекцию Song сущностей, которая содержит ссылку на сущность Artist и т. Д.,Вы можете увидеть, как он попадает в цикл при вызове метода toString и в конечном итоге исчерпывает кадры стека / достигает предела.

Либо удалите аннотацию @Data и примените только подмножество, либо определите свой собственныйtoString метод, который избегает петли.

...