如何使用自引用处理实体的RESTful响应 [英] How to handle RESTful response of Entity with self-reference
问题描述
我有一个Foo类,它引用了它自己。
这是我遇到的情况的粗略示例。
I have a class Foo which have reference to itself. This is rough example of situation I have been in.
@Entity
public class Foo() {
@Column(name = "id", unique = true, nullable = false)
private Long id;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_Foo")
private Foo parent;
}
当我将Foo对象传递给JSON响应生成器时,启动所有必需的getter并且JPA从DB检索到的所有必需数据。
When i pass Foo object to JSON response generator, all required getters are initiated and all required data retrieved from DB by JPA.
现在的问题是,如果我从自引用字段中删除@JsonIgnore,我将收到父信息和父父信息等等。
Now the problem is that if i remove @JsonIgnore from self-reference field I'm getting parent info, and parent parent info and etc.
我想要的是我可以限制检索到的父信息的深度。
例如。:
What I want is that I could limit deep of retrieved parent info. For example.:
- 深0 - 我只会得到Foo数据
- Deep 1 - 我将获得Foo和Foo父母的数据
- Deep 2 - 我将获得Foo和Foo父母和Foo父母的资料
等。
也许有一个带注释或smth的简单解决方案,因为我找不到任何东西。
Maybe there is a simple solution with annotations or smth, because i couldn't find anything.
编辑:
解决了自定义序列化程序和一些递归魔法的问题。
Solved this problem with custom serializer and some recursion magic.
private void serializeParents(JsonGenerator gen, Foo value, int currentDepth) {
if (currentDepth < PARENTS_DEPTH) {
if (value.getMom() != null) {
serializeParentData(gen, value.getMom(), currentDepth);
}
if (value.getDad() != null) {
serializeParentData(gen, value.getDad(), currentDepth);
}
}
}
private void serializeParentData(JsonGenerator gen, Foo value, int currentDepth) {
gen.writeObjectFieldStart(Gender.M.equals(value.getGender()) ? "dad" : "mom");
// other parameters ...
serializeParents(gen, value, currentDepth + 1);
gen.writeEndObject();
}
推荐答案
我认为最好的做法是是创建一个自定义DTO对象来收集所有 Foo
属性以及它的父
,所以你不会得到一个递归关系并避免延迟加载异常。
I think the best approach would be to create a custom DTO object to gather all your Foo
properties as well as its parent
, so you won't get a recursion relationship and avoid lazy loading exceptions.
所以你将保持你的实体不变:
So you will keep your entity as it is:
@Entity
public class Foo() {
@Column(name = "id", unique = true, nullable = false)
private Long id;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_Foo")
private Foo parent;
}
并创建一个这样的自定义DTO对象:
And create a custom DTO object like this:
public class FooDto() {
private Long id;
private Foo parent;
//getters and setters here
}
然后你可以使用此DTO将JSOn结果存储在您的请求中。
Then you can use this DTO to store JSOn results in your requests.
您可以查看 使用DTO(数据传输对象)的重点是什么? 了解更多详情。
You can take a look at What is the point of using DTO (Data Transfer Objects)? for further details.
@JsonIgnore
文档:
@JsonIgnore
documentation:
根据杰克逊 @JsonIgnore
文档 没有这样的选项(属性)来指定注释的深度/级别,因为只有一个可能property value
定义此anotation是否有效。
According to the Jackson @JsonIgnore
documentation there's no such option(property) to specify a depth/level for the annotation, as there's only one possible property value
to define if this anotation is active or not.
这篇关于如何使用自引用处理实体的RESTful响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!