当前位置: 首页 > 知识库问答 >
问题:

具有无限递归的双向关系

葛奇
2023-03-14

首先,这是我的实体。

玩家:

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, 
property="id")
public class Player {

    // other fields

    @ManyToOne
    @JoinColumn(name = "pla_fk_n_teamId")
    private Team team;

    // methods

}

团队:

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, 
property="id")
public class Team {

    // other fields

    @OneToMany(mappedBy = "team")
    private List<Player> members;

    // methods

}

正如已经说明的许多主题一样,您可以通过Jackson以多种方式避免WebService中的StackOverflow Exeption。

这很酷,除了JPA之外,在序列化之前,所有的实体都可以无限递归地构造另一个实体。这只是丑陋的ans请求需要更长的时间。检查这个截图:IntelliJ调试器

有办法解决吗?知道我希望根据endpoint获得不同的结果。示例:

    < li >endpoint/团队/{id} =

谢谢你!

编辑:也许这个问题并不能很清楚地给出我得到的答案,所以我会尽量更准确。

我知道可以通过杰克逊(@JSONIgnore,@JsonManagedReference/@JSONBackReference等)或通过对DTO进行一些映射来防止无限递归。我仍然看到的问题是:以上两者都是查询后处理。Spring JPA返回的对象仍然是(例如)一个团队,包含玩家列表,包含团队,包含玩家列表等。

我想知道是否有办法告诉JPA或存储库(或任何东西)不要一遍又一遍地绑定实体内的实体?

共有3个答案

贾飞章
2023-03-14

您可以使用@JsonIgnoreProperties注释来避免无限循环,如下所示:

@JsonIgnoreProperties("members")
private Team team;

或者像这样:

@JsonIgnoreProperties("team")
private List<Player> members;

或者两者兼而有之。

屠杰
2023-03-14

就我而言,我意识到我不需要双向(一对多多对一)关系。

这解决了我的问题:

java prettyprint-override">// Team Class:
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Player> members = new HashSet<Player>();

// Player Class - These three lines removed:
// @ManyToOne
// @JoinColumn(name = "pla_fk_n_teamId")
// private Team team;

龙目岛项目也可能产生这个问题。尝试添加@ToString,如果您使用的是龙目岛,请@EqualsAndHashCode

@Data
@Entity

@EqualsAndHashCode(exclude = { "members"}) // This,
@ToString(exclude = { "members"}) // and this

public class Team implements Serializable {

// ...


这是一个关于无限递归注释的很好的指南

慕翰学
2023-03-14

下面是我如何在我的项目中处理这个问题。

我使用了数据传输对象的概念,在两个版本中实现:完整对象和轻对象。

我将包含引用实体的对象定义为 List as Dto(仅保存可序列化值的数据传输对象),并将没有引用实体的对象定义为 Info

Info对象仅保存有关实体本身的信息,而不包含有关关系的信息。

现在,当我通过 REST API 交付 Dto 对象时,我只是将 Info 对象放在引用中。

假设我在< code>GET /players/1上交付了一个< code>PlayerDto:

public class PlayerDto{
   private String playerName;
   private String playercountry;
   private TeamInfo;
}

天文旅对象看起来像

public class TeamInfo {
    private String teamName;
    private String teamColor;
}

与< code>TeamDto相比

public class TeamDto{
    private String teamName;
    private String teamColor;
    private List<PlayerInfo> players;
}

这避免了无休止的序列化,并且还为您的Rest资源提供了一个合乎逻辑的结局,因为在其他方面,您应该能够获得/玩家/1/团队/玩家/1/团队

此外,这个概念清楚地将数据层与客户端层(在本例中是REST API)分开,因为您并没有将实际的实体对象传递给接口。为此,您将服务层中的实际实体转换为< code>Dto或< code>Info。为此我使用了http://modelmapper.org/,因为它非常简单(一个简短的方法调用)。

此外,我懒洋洋地获取所有引用的实体。我的服务方法获取实体并将其转换为在html" target="_blank">事务范围内运行的< code>Dto,无论如何这都是一个好的实践。

要告诉 JPA 懒惰地获取实体,只需通过定义提取类型来修改关系注释即可。此项的默认值为“获取 = 提取类型”,这在你的情况下是有问题的。这就是为什么你应该把它改成“抓取=抓取类型”。

public class TeamEntity {

    @OneToMany(mappedBy = "team",fetch = FetchType.LAZY)
    private List<PlayerEntity> members;
}

同样,玩家

public class PlayerEntity {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pla_fk_n_teamId")
    private TeamEntity team;
}

从服务层调用存储库方法时,重要的是,这是在@Transactional范围内发生的,否则,您将无法获得延迟引用的实体。看起来是这样的:

 @Transactional(readOnly = true)
public TeamDto getTeamByName(String teamName){
    TeamEntity entity= teamRepository.getTeamByName(teamName);
    return modelMapper.map(entity,TeamDto.class);
}
 类似资料:
  • 我在一个使用SpringBoot2.0、Hibernate和SpringDataREST的项目中工作。前端带有React 我遇到过这样的情况:一个用户可以与多家公司(他拥有多家公司)链接 当我尝试使用UserRepository或CompanyRepository获取一些实体时,我得到了错误:无法写入JSON:Infinite recursion(StackOverflowerError);嵌套的

  • 问题内容: 我使用Gson 库将Java对象转换为Json响应…问题是,在JPA请求之后,由于与其他实体的递归关系,无法转换从DB检索到的对象: 我的源代码: 如您在这里看到的,我做了: 只是通过为coordonneesList中的每个GPS对象设置null来消除递归关系。 您认为这是一个很好的解决方案,或者还有其他更实用的方法吗?谢谢 问题答案: 有一个名为GraphAdapterBuilder

  • 问题内容: 我有一个类似(简化)的表结构: 内容 content_has_content topic_has_content 任何主题都可以具有多个“内容”,任何“内容”都可以具有多个“子内容”(内容实例)。对于给定的id_topic,我想从链接的内容,子内容,子内容的子内容等中接收所有my_string1的列表。 我了解“ WITH”不适用于mysql,但找不到很好的递归替代方法。 谢谢丹尼尔

  • 问题内容: 我期望以下内容返回所有元组,将层次结构中的每个父级解析到顶部,但它仅返回最低级别(在查询中指定了其ID)。如何为给定的level_id返回整棵树? 问题答案: 首先,如果您确实是祖父母,则应该如此。其次,您在查询的递归一半中的(隐式)连接条件是向后的,您想让父级脱离,而不是:

  • 我对Spring集成相对较新,但我的任务是实现一个tcp网关,该网关需要: 在套接字上侦听消息 在我的Spring集成经验中,消息流不是双向的。我只将路由器配置为侦听、处理消息和输出到队列/主题。但是,在这种情况下,我需要接受消息并返回响应,同时将某些消息转发到队列。建议? 这是到目前为止我的集成xml。 如何将handleInput的输出转发到队列,同时从网关返回一些响应? 编辑:在与Gary进

  • 我用的是Spring Roo 1.2.1和Jackson 1.9.7。在使用json序列化我的类时,我得到了一个JsonMappingException。 我读了以下帖子,但没有找到适合我的工作解决方案: Jackson的无限递归 Jackson-具有双方向关系的实体序列化(避免循环) 我不知道为什么JsonIgnore在属性QueueOuts的类Queue中不起作用。我也尝试了JsonManag