java - 将@OneToMany 与@RestController 关系使用而不进行无限缩减的最佳实践是什么
问题描述
我有以下内容:
@Data
@Entity
@Table(name = "floor")
public class Floor {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "floor_id")
private Long id;
@JsonIgnoreProperties(value= {"floor", "registrations"})
@OneToMany (mappedBy = "floor", cascade = CascadeType.ALL)
private Set<Slot> slots;
}
@Entity
@Table(name = "slot")
public class Slot {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "slot_id")
private Long id;
@ManyToOne
@JoinColumn(name = "floor_id")
private Floor floor;
}
@RestController
public class Controller {
@Autowired
FloorService floorService;
@GetMapping("/api/floors")
public List<Floor> getAllFloors() {
// calls repository.findAll()
return floorService.getAllFloors();
}
}
访问 API 端点时,我得到:
2021-03-06 06:52:30.038 WARN 699889 --- [tp1028811481-19] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]->com.veebzone.parking.model.Floor["slots"])]
通过使用 /api/floors 端点获取每个楼层的列表,我的目标是在其 JSON 元素中获取与每个楼层关联的插槽列表。
实现这一目标的最佳做法是什么:
- 我的方法是正确的,只是一些配置问题?
- 我应该改用服务返回的一些 DTO(将插槽列表作为子元素)并使用 JSONIgnore 作为插槽字段。
- 别的东西
解决方案
我假设您在调用端点时想要这样的东西(一组楼层,每个楼层都有一组插槽):
[
{ "id": 1,
"slots": [
{ "id": 1 },
{ "id": 2 }
]
},
{ "id": 2,
"slots": [
{ "id": 3 }
]
}
]
您有一个无限递归,因为 Jackson 是 Spring Boot 中用于写入/读取 Json 的默认库(就像在您的 enpoint 中一样),它尝试使用您类中的每个字段来构建 Json。
所以发生的事情是,Jackson 试图在输出 Json 中写入第一层,但这一层与第一个插槽有关,它与第一层有关,依此类推。这是你的循环。
如果你想打破循环,你有两个选择:
- 删除Floor类中的@JsonIgnoreProperties(value= {"floor", "registrations"}) ,然后在Slot类的 floor 字段上添加@JsonIgnore 。这样,杰克逊就不会序列化该字段。
- 使用@JsonSerialize为Floor类构建您自己的序列化程序(参见此)。
现在,哪个选项更好将取决于您的实体有多大以及实体之间的关系有多复杂。
推荐阅读
- python - 如何使用 urllib3 获取 URL 的 Content-Type
- reactjs - 在 reactjs 中创建 XML 文件
- javascript - 在输入范围的两个部分应用不同的颜色
- xamarin - Xamarin.Android Java 绑定库运行时失败访问本机库
- blockchain - 发送和发送多 API
- java - 在 sts 中嵌入 apache tomcat 服务器无法启动
- c# - 如何访问不同的用户证书存储?
- angular - 如何缓存一个 observable 并始终为它服务?
- python - 给定一系列数据,找到给定时间段的持续时间限制?
- reporting-services - 用于报告的 Power BI 与 SSRS