我在一个Spring项目中,发现自己遇到了一个循环引用问题,与这里已经发布的问题有点不同(至少是我设法找到的问题)。
类结构
应用程序有一个用户类/实体。这个实体可以向其他用户发送“鸭子”。它与已经发送“鸭子”的用户有一个聚合关系(一个列表),另一个列表与已经向您发送“鸭子”的用户。(它是一个M-N基数关系)
@Entity
public class User{
@ManyToMany
@JsonManagedReference
@JoinTable(
name = "sendsDuck",
joinColumns = @JoinColumn(name = "sender"),
inverseJoinColumns = @JoinColumn(name = "receiver")
)
private Set<User> duckedUsers;
@ManyToMany(mappedBy = "duckedUsers")
@JsonBackReference
private set <User> receivesDuckFrom;
//Getters and setters
...
}
正如您所看到的,我添加了@JsonManagedReference
和@JsonBackReference
标记,以精确地避免自引用或循环引用。
问题
问题是,当一个用户向另一个用户发送“duck”时,我上面提到的标记解决了循环引用问题。然而,当两个用户互相发送敏感的duck(A发送给B,B发送给A)时,我有一个循环引用,我不知道如何处理。
这是因为这两个对象在同一个duckedUsers
属性中有另一个对象。
我都试过什么?
以下是我迄今为止所做的尝试,但没有成功:
- @ JSON忽略
如果我把这个注解放在duckedUsers
属性上,它可以正常工作。但是,API客户端需要知道它向其发送鸭子的用户的数据,所以这个解决方案不足以满足我的情况。
- @JsonManagedReference和@JsonBackReference位于同一属性上
有点愚蠢的尝试,但是尝试在同一个属性上同时使用这两个注解,即使它们没有多大意义。
@ManyToMany
@JsonManagedReference
@JoinTable(
name = "sendsDuck",
joinColumns = @JoinColumn(name = "sender"),
inverseJoinColumns = @JoinColumn(name = "receiver")
)
- 对象Map器
在控制器内部,尝试使用按以下方式配置的objectMapper:
一个二个一个一个
像这样使用它:
@PostMapping("/sendDuck")
ResponseEntity sendDuck(@RequestParam Long transmitterId, @RequestParam Long receiverId) {
User transmitter = this.findOrThrow(transmitterId);
User receiver = this.findOrThrow(receiverId);
transmitter.sendsDuck(receiver);
repository.save(transmitter);
repository.save(receiver);
List<User> usersList = List.of(receiver, transmitter);
CollectionModel<EntityModel<User>> body = this.collectionModelFromList(usersList);
try{
String serializedBody = objectMapper.writeValueAsString(body);
return ResponseEntity.ok().body(body);
}catch (IOException ex){
String errorMessage = "JSON serializing error: " + ex.getMessage();
return ResponseEntity.internalServerError().body(errorMessage);
}
}
这一尝试也没有成功。
我认为解决方案应该是什么样的?
从目前为止我所看到的,我明白我想要实现的是一个JSON响应,它的工作方式是只有当实体是响应中的子实体时才应用@JsonIgnore
。类似这样:
{
id:1,
...
duckedUsers:[
{
id:1,
...
duckedUsers:... //This must NOT appear as is a child entity
},
]
}
1条答案
按热度按时间68de4m5k1#
正如@Rogue在评论中解释的那样,更好的解决方案是将User实体和Ducks关系解耦。这是代码的结尾:
用户实体
鸭子实体