JPA OneToMany, как игнорировать поле ManyToOne при печати в консоли или веб-приложении - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть 2 таблицы: жанры (genre_id, genre_name) и фильмы (movie_id, movie_name, movie_score, genre_id).genre_id_fk из фильмов, на которые ссылается genre_id в жанрах.

@Entity
@Table(name = "genres", schema = "test")
public class Genre {

@Id
@Column(name = "genre_id")
private int id;
@Column(name = "genre_name")
private String name;
@OneToMany(mappedBy = "genre", fetch = FetchType.LAZY)
private List<Movie> movies = new ArrayList<>();
}

и 2-й объект для фильмов

@Entity
@Table(name = "movies", schema = "test")
public class Movie {

@Id
@GeneratedValue
@Column(name = "movie_id")
private int id;
@Column(name = "movie_name")
private String name;
@Column(name = "movie_score")
private double score;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "genre_id")
private Genre genre;
}

, когда я пытаюсь распечатать его в консоли с этим кодом:

public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
    EntityManager em = emf.createEntityManager();
    Genre genre = em.find(Genre.class, 1);
    System.out.println(genre);
}

получение Exception in thread "main" java.lang.StackOverflowError только удаление из toString () в поле класса «жанры» фильма может исправить это.Но возможно ли этого избежать?И та же самая проблема с приложением весенней загрузки

@RestController
public class GenreController {

@Autowired
private GenreService genreService;

@RequestMapping("/test/{id}")
public List<Genre> getGenreInfo(@PathVariable int id){
    return genreService.getGenreFilms(id);
}
}

здесь обслуживает

@Service
public class GenreService {

public List<Genre> getGenreFilms(int id){
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
    EntityManager em = emf.createEntityManager();
    List<Genre> genres = new ArrayList<>();
    Genre genre = em.find(Genre.class, id);
    genres.add(genre);
    return genres;
}
}

и получает эту проблему как: [{"id": 1, "name": "Thriller", "movies ": [{" id ": 1," name ":" Any, с вами все в порядке? "," score ": 5.45," genre ": {" id ": 1," name ":" Thriller ","movies ": [{" id ": 1," name ":" Any, с вами все в порядке? "," score ": 5.45," genre ": {" id ": 1," name ":" Thriller ","movies ": [{" id ": 1," name ":" Any, с тобой все в порядке? "," score ": 5.45," genre ": .... и до бесконечности с мягким исключением.Консоль я могу исправить только игнорированием поля в методе toString ().Но как исправить эту проблему в веб-приложении?

здесь журнал отладки гибернации, когда консольная печать

22:15:37.154 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - 
Resolving associations for [com.company.Genre#1]
22:15:37.164 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done 
materializing entity [com.company.Genre#1]
22:15:37.164 [main] DEBUG 
org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - 
HHH000387: ResultSet's statement was not registered
22:15:37.165 [main] DEBUG 
org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader - Done 
entity load : com.company.Genre#1
22:15:37.165 [main] DEBUG 
org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - 
Initiating JDBC connection release from afterTransaction
22:15:37.167 [main] DEBUG org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer 
- Loading collection: [com.company.Genre.movies#1]
22:15:37.167 [main] DEBUG org.hibernate.SQL - select movies0_.genre_id as 
genre_id4_1_0_, movies0_.movie_id as movie_id1_1_0_, movies0_.movie_id as 
movie_id1_1_1_, movies0_.genre_id as genre_id4_1_1_, movies0_.movie_name as 
movie_na2_1_1_, movies0_.movie_score as movie_sc3_1_1_ from test.movies 
movies0_ where movies0_.genre_id=?
Hibernate: select movies0_.genre_id as genre_id4_1_0_, movies0_.movie_id as 
movie_id1_1_0_, movies0_.movie_id as movie_id1_1_1_, movies0_.genre_id as 
genre_id4_1_1_, movies0_.movie_name as movie_na2_1_1_, movies0_.movie_score 
as movie_sc3_1_1_ from test.movies movies0_ where movies0_.genre_id=?
22:15:37.168 [main] DEBUG 
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - 
Preparing collection intializer : [com.company.Genre.movies#1]
22:15:37.170 [main] DEBUG 
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - 
Starting ResultSet row #0
22:15:37.171 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerIm 
pl - Found row of collection: [com.company.Genre.movies#1]
22:15:37.171 [main] DEBUG 
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - 
Starting ResultSet row #1
22:15:37.172 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerIm 
pl - Found row of collection: [com.company.Genre.movies#1]
22:15:37.172 [main] DEBUG 
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl - 
Starting ResultSet row #2
22:15:37.172 [main] DEBUG org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerIm 
pl - Found row of collection: [com.company.Genre.movies#1]
22:15:37.172 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - 
Resolving associations for [com.company.Movie#1]
22:15:37.172 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done 
materializing entity [com.company.Movie#1]
22:15:37.173 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - 
Resolving associations for [com.company.Movie#2]
22:15:37.173 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done 
materializing entity [com.company.Movie#2]
22:15:37.173 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - 
Resolving associations for [com.company.Movie#3]
22:15:37.173 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done 
materializing entity [com.company.Movie#3]
22:15:37.173 [main] DEBUG 
org.hibernate.engine.loading.internal.CollectionLoadContext - 1 collections 
were found in result set for role: com.company.Genre.movies
22:15:37.173 [main] DEBUG 
org.hibernate.engine.loading.internal.CollectionLoadContext - Collection 
fully initialized: [com.company.Genre.movies#1]
22:15:37.173 [main] DEBUG 
org.hibernate.engine.loading.internal.CollectionLoadContext - 1 collections 
initialized for role: com.company.Genre.movies
22:15:37.173 [main] DEBUG 
org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl - 
HHH000387: ResultSet's statement was not registered
22:15:37.173 [main] DEBUG org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer 
- Done loading collection
Exception in thread "main" java.lang.StackOverflowError

, скажите мне, где я делаю ошибку и как исправить или погуглить эту проблему?просто не печатать этот объект по localhost: 8080 / genre / id?сделать что-то конкретное напечатать или что?

1 Ответ

0 голосов
/ 22 декабря 2018

Кажется, что у вас есть бесконечная рекурсия при попытке toString ваших Genre сущностей.Ваш код сначала загружает вашу сущность Genre по идентификатору, а затем вызывает Genre.toString().Поскольку у вас @OneToMany отношения с Movie s, он lazy loads выводит список, а затем вызывает Movie.toString() для каждого фильма, связанного с жанром.Тогда для каждого фильма у вас есть отношения @ManyToOne с жанром.И здесь кроется проблема.Он будет вызывать снова Genre.toString() для каждого фильма в списке.

Возможные решения

  1. Если вы хотите просто напечатать его в консоли, не включайте список фильмов в Genre.toString()
  2. Если вы используете Джексона, добавьте @JsonBackReference к вашему @ManyToOne отношению в Movie, таким образом Джексон будет игнорировать его при сопоставлении с Json Документация по аннотации здесь
  3. Если вы используете DTO, просто не включайте свойство Movie в ваше DTO.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...