Ошибка StackOverflowError при попытке вывести список
Получаю ошибку при попытке вывести список Movies(Director->Movies: Один к Многим). В чем может быть причина?
package org.example.model;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Data
@Entity
@Table(name = "Direct")
public class Direct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "onwer")
private List<Movies> moviesList;
}
package org.example.model;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "Movies")
public class Movies {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "title")
private String title;
@ManyToOne
@JoinColumn(name = "direct_id", referencedColumnName = "id")
private Direct onwer;
}
package org.example;
import org.example.model.Direct;
import org.example.model.Movies;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import java.util.List;
public class App {
public static void main( String[] args ) {
Configuration configuration = new Configuration().addAnnotatedClass(Direct.class)
.addAnnotatedClass(Movies.class);
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
try {
session.beginTransaction();
Direct direct = session.get(Direct.class, 3);
System.out.println(direct.getName());
System.out.println(direct.getId());
List<Movies> movies = direct.getMoviesList();
System.out.println(movies.toString());
session.getTransaction().commit();
} finally {
session.close();
sessionFactory.close();
}
}
}
# (Data source)
hibernate.driver_class=org.postgresql.Driver
hibernate.connection.url=jdbc:postgresql://localhost:5432/hiber_demo
hibernate.connection.username=postgres
hibernate.connection.password=12345
# Hibernate
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql=true
hibernate.current_session_context_class=thread
Ответы (1 шт):
Оба класса помечены Lombok-аннотацией @Data, следовательно, в обоих классах переопределён метод toString, при вызове которого и происходит зацикливание: Movie::toString печатает Direct onwer и соответственно вызывает Direct::toString, который печатает список фильмов и для каждого Movie снова вызывает toString.
Для разрыва этой цепочки следует исключить вызов toString, например, при помощи Lombok-аннотации ToString.Exclude для одного или обоих полей:
@Data
@Entity
@Table(name = "Movies")
public class Movies {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "title")
private String title;
@ManyToOne
@JoinColumn(name = "direct_id", referencedColumnName = "id")
@ToString.Exclude private Direct onwer;
}
Возможно, также понадобится исключить поля из методов 'equals/hashCode' при помощи аналогичной аннотации @EqualsAndHashCode.Exclude
Аналогичная проблема может возникнуть и при сериализации данных сущностей в JSON, тогда придется использовать аннотации @JsonManagedReference / @JsonBackReference, чтобы избежать зацикливания.
