以递归关系解决StackOverflow异常

时间:2019-05-18 22:51:30

标签: java json

我在实体之间具有递归关系,而当我的剩余api将其转换为JSON时,我得到了StackOverflow异常,这是我完全理解的。

Jersey使用yasson作为默认的JSON提供程序,并且我找到了一个解决方案,您可以在序列化时使用@JsonbTransient忽略对象中的属性。我的用户类别有一个推文列表,一个推文有一个用户。因此,我在User类的tweets列表属性中添加了@JsonbTransient。

用户类别:

public class User {
    ...
    @JsonbTransient
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    private List<Tweet> tweets;
    ...
}

推文类:

public class Tweet {
    ...
    @ManyToOne
    private User user;
    ...
}

我想在访问相关用户的某些属性时呈现所有(来自不同用户)推文的列表。但是我也想在同一页面上呈现用户的推文列表(获取推文计数等)。仅仅忽略用户类上的推文列表还不够。

是否还有一个注释,提供了一种序列化这种关系的方法,而不必完全忽略第一层的属性,但会更深一层。

例如:当您知道自己在拥有用户的Tweet对象中时,该用户将忽略其推文列表,并且当该用户不在某个tweet对象中时,其推文列表将不会被忽略。还是根本不可能?

有人将如何解决这样的问题?

我当然可以忽略用户中的tweets列表属性,当我想要相应用户的tweet时,可以在另一个调用中检索它们。 (不要与延迟加载相混淆,因为我希望一开始就将两个数据都包含在内)

但是我的想法是,可能会有一个神奇的注释可以自动解决此问题。在那吗?

谢谢,

迈克

1 个答案:

答案 0 :(得分:2)

您将API模型与数据库模型绑定得太紧了。不要那样做。

您的API希望返回一个带有根用户对象的模型,该对象具有详细信息,包括鸣叫列表,并且一条鸣叫想要标识该用户,但不希望 full 详细用户对象,即只需要用户引用。

示例:

{
  "UserId": 1,
  "UserName": "Bob",
  "UserEmail": "bib@example.com",
  "Tweets": [
    {
      "User": {
        "UserId": 2,
        "UserName": "Alice",
      },
      "Text": "Hello Bob"
  ]
}

如您所见,内部用户对象是MiniUser,外部用户对象是FullUser (任意名称,您可能希望将它们称为其他名称)

因此,请从DAO模型中创建API模型。不要使DAO模型成为API模型。