Hibernate @OneToMany关系导致JSON结果中的无限循环或空条目

Goo*_*oot 15 json hibernate one-to-many hibernate-onetomany

我有两个实体,一个实体"电影"和一个实体"剪辑"每个剪辑属于一个电影,一个电影可以有多个剪辑.

我的代码看起来像:

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;
Run Code Online (Sandbox Code Playgroud)

正在生成表,每个Clip都有一个列"movie_id"但这会导致我的应用程序在我请求数据时最终处于无限循环中

    @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...
Run Code Online (Sandbox Code Playgroud)

当我请求剪辑时,结果相同.

当我将它改为@ManyToMany关系时,不会有任何类似的问题,但这不是我在这里需要的.你能帮助我吗?将fetchType设置为Lazy不起作用.

编辑:我正在使用当前的JBoss开发工作室

编辑:

通过阅读本文,我"解决了"这个问题:

http://blog.jonasbandi.net/2009/02/help-needed-mapping-bidirectional-list.html

"要将双向一个映射到多个,一对多一侧作为拥有方,您必须删除mappedBy元素并将多个@JoinColumn设置为可插入且可更新为false.此解决方案显然未进行优化并会产生一些额外的UPDATE语句."

当我要求电影时,我得到以下答案:

{"id":1,"version":1,"name":"MGS Walkthrough","filename":"video.mp4","movieCategories":[{"id":1,"version":1, "名称":"演练"}],"剪辑":[],"说明":"预告片zu mgs4"}

条目"剪辑"仍然出现.这仍然是错误的解决方案还是我必须忍受这个?

Din*_* Tw 17

我遇到了完全相同的问题.我尝试了引用段落中的解决方案,它对我不起作用.

我所做的是在Clip类中为getMovie()返回null,然后无限循环问题就消失了.以JSON格式返回的数据看起来像{"movieId":1 ... clips:["clipId":1,"movie":"null",..]}.

如果您还想在JSON中进一步删除movie属性,请将类级注释添加到Clip类@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)

杰克逊功能:防止空值序列化,默认值

更新:我找到的更简单的方法是在Clip类中删除电影的getter.


btd*_*337 15

解:

使用

@JsonManagedReference 实例化的第一个对象的注释

@JsonBackReference 实例化的第二个对象的注释

Movie.java

@JsonManagedReference
@OneToMany(mappedBy = "movie", targetEntity = Clip.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Clip> clips = new HashSet<Clip>();
Run Code Online (Sandbox Code Playgroud)

Clip.java

@JsonBackReference
@ManyToOne
    @JoinColumn(name="movie_id")
    private Movie movie;
Run Code Online (Sandbox Code Playgroud)


Dai*_*Niu 6

首先,让我向您展示为什么将 fetch type 设置为 lazy 没有帮助。当您尝试序列化您的 pojo 时,您的序列化程序(可能是 jackson)会调用此 pojo 的每个 getter,并将 getter 的返回值用作 json 数据中的属性。所以它显式调用 getter,它调用 hibernate 来加载关联的实体(用于 Clip 的 movie 和用于 Movie 的 clips)。所以你需要使用@JsonIgnoreProperties来摆脱这个奇怪的无限循环,代码是这样的:

Clip.java

    @ManyToOne
    @JoinColumn(name="movie_id")
    @JsonIgnoreProperties("clips")
    private Movie movie;

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

这样,您会发现剪辑 json 对象中的嵌套电影在电影中没有“剪辑”,电影中的嵌套剪辑也没有“电影”子级。

我想这是处理这个问题的最好方法,也是开发java web app的最佳实践。