0

我想知道如何使用具有双向关系的 Spring REST 处理序列化。我目前正在使用 Spring Boot 1.3.0.BUILD-SNAPSHOT

目前,我收到内部服务器错误,说明主类存储库上的 GET 请求无限递归。

它适用于两个类,其中一个是存储库。在示例 A 中,A 是具有存储库的示例:

@Entity
public class A implements Serializable {
    private static final long serialVersionUID = 1L;

    @OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<B> b;

    public A() {

    }
    public List<B> getB() {
        return b;
    }
    public void setCategory(List<B> b) {
        this.b = b;
        for (B oneB : this.category) {
            oneB.setA(this);
        }
    }
}

@Entity
public class B implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToOne
    @JoinColumn(name = "b_column")
    @JsonBackReference
    @RestResource(rel = "BParent")
    private A a;

    public B() {

    }
    public A getA() {
        return a;
    }
    public void setA(A a) {
        this.a = a;
    }
}

但是,如果我在 B 中添加另一个类,它将不再起作用,并且如果我向 A 的存储库发送 GET 请求(C 在其 b 属性上具有与 B 相同的注释),我将获得无限递归:

@Entity
public class B implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToOne
    @JoinColumn(name = "b_column")
    @JsonBackReference
    @RestResource(rel = "BParent")
    private A a;

    @OneToMany(mappedBy = "c", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<C> c;

    public B() {

    }
    public A getA() {
        return a;
    }
    public void setA(A a) {
        this.a = a;
    }
}

因此,根据我的观察,我可以在对 B 的反向引用中省略 C 类中的 Jackson 注释,而不会改变行为。这是已知的行为还是我错过了什么?

更新 1

我试图通过修改B类并删除C上的反向引用来摆脱B和C对象之间的双向关系:

@Entity
public class B implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToOne
    @JoinColumn(name = "b_column")
    @JsonBackReference
    @RestResource(rel = "BParent")
    private A a;

    //This is now a unidirectional relationship to C
    @NotNull
    @OneToMany
    @JoinColumn(name="b_id", referencedColumnName="id")
    private List<C> c;

    public B() {

    }
    public A getA() {
        return a;
    }
    public void setA(A a) {
        this.a = a;
    }

    public List<C> getC() {
    return c;
    }

    public void setC(List<C> c) {
       this.c= c;
    }
}

虽然这消除了对 A 的存储库的 GET 请求的无限递归(万岁!),但它也消除了在向 A 的存储库发送 POST 时存储 C 对象的可能性(嘘!)。这将抛出此错误消息:

org.hibernate.TransientObjectException: 对象引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例

更新 2

我试图为 B 类添加一个存储库。这导致了另一个无限递归。但是这一次应用程序和 IDE 只是因为错误没有得到正确处理而崩溃。

4

1 回答 1

0

所以基本上如果我将对象 B 定义为存储库并用

@RestResource(exported = false)
@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
@JsonManagedReference
private List<B> b;

如果以这种方式注释对象 C 将被正确序列化而没有任何无限递归废话。

如果有人有很好的解释或解决方案,我会很乐意将其标记为答案。


关于春季休息的有趣事实

Spring Rest 对具有多个连续大写字母的变量/类名存在一些问题。例如,一个名为的类的存储库

public class ACos

将无法正常工作,并且名为

private String aCos;

将被序列化为

{“acos”:“随便”}

于 2015-11-11T22:37:18.867 回答