jsonhibernateone-to-manyhibernate-onetomany

Hibernate @OneToMany Relationship Causes Infinite Loop Or Empty Entries in JSON Result


I have two entities, an entity "movie" and an entity "Clip" each clip belongs to one movie and a movie can have multiple clips.

My code looks like:

Movie.java
    @OneToMany(mappedBy = "movie", targetEntity = Clip.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Clip> clips = new HashSet<Clip>();


  
 Clip.java
    
    @ManyToOne
        @JoinColumn(name="movie_id")
        private Movie movie;

The tables are being generated and each Clip has a column "movie_id" but this causes my application to end up in an infinite loop when I'm requesting Data

    @Path("/{id:[0-9][0-9]*}")
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public Movie lookupMovieById(@PathParam("id") long id) {
            return em.find(Movie.class, id);
        }
    

result:
{"id":1,"version":1,"name":"MGS Walkthrough","filename":"video.mp4","movieCategories":[{"id":1,"version":1,"name":"Walkthrough"}],"clips":[{"id":1,"version":1,"name":"MGS Walkthrough P1","keywords":null,"movie":{"id":1,"version":1,"name":"MGS Walkthrough","filename":"video.mp4","movieCategories":[{"id":1,"version":1,"name":"Walkthrough"}],"clips":[{"id":1,"version":1,"name":"MGS Walkthrough P1","keywords":null,"movie":{"id":1,"version":1,"name":"MGS Walkthrough","filename":"video.mp4","movieCategories":[{"id":1,"version":1,"name":"Walkthrough"}],"clips":[{"id":1,"version":1,"name":"M...

It's the same result when I'm requesting a clip.

When I change it to a @ManyToMany relationship there won't be any problems like that, but that's not what I need here. Can you help me? Setting fetchType to Lazy didn't work.

Edit: I'm using the current JBoss development studio

Edit:

I "solved" this, by reading this article:

https://web.archive.org/web/20180401022123/http://blog.jonasbandi.net/2009/02/help-needed-mapping-bidirectional-list.html

"To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is obviously not optimized and will produce some additional UPDATE statements."

when I request a movie I get the following answer:

{"id":1,"version":1,"name":"MGS Walkthrough","filename":"video.mp4","movieCategories":[{"id":1,"version":1,"name":"Walkthrough"}],"clips":[],"description":"Trailer zu mgs4"}

the entry "clips" still appears. Is this still the wrong solution or do I just have to live with this?


Solution

  • I ran into exactly the same problem. I tried the solution from the quoted paragraph, it did not work for me.

    What I did is to return null for getMovie() in Clip class, then the infinite loop issue is gone. The data returned in JSON format will look like {"movieId":1 ... clips:["clipId":1, "movie":"null", ..]}.

    If you also want further remove the movie property in JSON, add the class-level annotation to Clip class @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

    Jackson feature: prevent serialization of nulls, default values

    Update: The easier way I found is to simply remove the getter of movie in Clip class.