JPA关系的无限递归(OneToMany和ManyToOne)

时间:2014-08-15 16:26:59

标签: json jpa jackson one-to-many many-to-one

我有两个JPA实体,Message和File,它们之间有以下关系:

public class Message implements Serializable {
   ...
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "message")
   @JsonManagedReference
   private List<File> files;
   ...
}

public class Anexo implements Serializable {
   ...
   @ManyToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "id_mensagem")
   @JsonBackReference
   private Message message;
   ...
}

当我尝试使用EntityManager进行查询,插入或更新时,一切都很好......当我尝试删除时,我收到以下错误:

Ago 15, 2014 1:21:43 PM com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
Grave: The exception contained within MappableContainerException could not be mapped to a response, re-throwing to the HTTP container
java.lang.StackOverflowError

我可以调试并看到Message对象每个都有一个Files集合,每个File都有一个Message,它有一个Files集合,每个都带有一个Message等等......

为什么插入,更新和查询这不是问题,但是在删除时是什么?

1 个答案:

答案 0 :(得分:0)

您似乎在 Anexo 类中使用了一些不安全的方法,或者为每个Anexo创建了一个新的Message引用。

注意:我认为你在课堂上的意思是private List<Anexo> files;

您可以尝试使用 setMessage 方法:

public void setMessage(Message message) {
    // this is a loop-preventing part
    if (sameAsFormer(message)) {
        return;
    }

    Message formerMessage  = this.message;
    this.message = message;

    if (formerMessage  != null) {
        // this is important, but easy to forget
        formerMessage.removeAnexo(this);
    }

    if (message!= null) {
        message.addAnexo(this);
    }
}

方法 sameAsFormer 类似于:

private boolean sameAsFormer(Message message) {
    return this.message==null ? message==null : this.message.equals(message);
}

消息中的 removeAnexo addAnexo 方法类似于:

public void addAnexo(Anexo anexo) {
    if(getFiles().contains(anexo)) {
        getFiles().set(getFiles().indexOf(anexo), anexo);
    } else {
        getFiles().add(anexo);
    }
    anexo.setMessage(this);
}

public void removeAnexo(Anexo anexo) {
    getFiles().remove(anexo);
    anexo.setMessage(null);
}

请查看this linkthis link

希望它有所帮助。