簡體   English   中英

JPA OneToMany,在控制台或Webapp中打印時如何忽略字段ManyToOne

[英]JPA OneToMany , how to ignore field ManyToOne when print in console or webapp

我有2個表格:類型(genre_id,genre_name)和電影(movie_id,movie_name,movie_score,genre_id)。 風格中引用genre_id的電影中的genre_id_fk。

@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<>();
}

電影的第二實體

@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);
}

僅在電影類字段“類型”中的toString()中刪除,才能Exception in thread "main" java.lang.StackOverflowError接收到Exception in thread "main" java.lang.StackOverflowError可以解決該問題。 但是有可能避免嗎? 和Spring Boot應用程序相同的問題

@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”:“好嗎?”,“得分” :5.45,“類型”:{“ id”:1,“名稱”:“驚悚片”,“電影”:[{“ id”:1,“名稱”:“任何,你還好嗎?”,“得分” :5.45,“類型”:{“ id”:1,“名稱”:“驚悚片”,“電影”:[{“ id”:1,“名稱”:“任何,你還好嗎?”,“得分” :5.45,“ genre”:....並無窮無盡。 控制台我可以通過忽略toString()方法中的字段來解決。 但是如何在Web應用程序中解決此問題?

在控制台打印時,這里是休眠調試日志

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打印此對象? 做一些特別的印刷品或什么?

好像你想的時候有一個無限循環toString您的Genre實體。 您的代碼首先通過id加載您的Genre實體,然后調用Genre.toString() 因為您與Movie具有@OneToMany關系,所以它會lazy loads列表,然后為與該流派相關的每個電影調用Movie.toString() 然后,對於每部電影,您都與Genre有@ManyToOne關系。 問題就在這里。 它將為列表中的每個電影再次調用Genre.toString()

可能的解決方案

  1. 如果只想在控制台中簡單地打印它,則不要在Genre.toString()包括電影列表。
  2. 如果您使用的是Jackson,請將@JsonBackReference添加到Movie@ManyToOne關系中,這樣,當Jackson映射到此處的 Json Annotation文檔時,Jackson將忽略它
  3. 如果使用DTO,則不要在DTO中包含Movie屬性。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM