Я хотел бы узнать разницу между @JsonManagedReference
и @JsonBackReference
в Джексоне?
JsonManagedReference vs JsonBackReference
Ответ 1
@JsonManagedReference - это прямая часть ссылки - та, которая обычно сериализуется. @JsonBackReference - это задняя часть reference - он будет опущен из сериализации.
Таким образом, они действительно зависят от направления ваших отношений.
public class User {
public int id;
public String name;
@JsonBackReference
public List<Item> userItems;
}
public class Item {
public int id;
public String itemName;
@JsonManagedReference
public User owner;
}
Ответ 2
@JsonManagedReference
и @JsonBackReference
предназначены для обработки этой двухсторонней связи между полями, одна для родительской роли, другая для роли Child.
Чтобы избежать проблемы, привязка обрабатывается таким образом, что свойство аннотируется с аннотацией @JsonManagedReference, обрабатывается нормально (сериализованные обычно, без специальной обработки для десериализации) и свойство, аннотированное аннотацией @JsonBackReference, не сериализованная; и во время десериализации его значение устанавливается на экземпляр который имеет "управляемую" (прямую) ссылку.
Ответ 3
Я предпочитаю @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
, где свойство - это имя поля первичного ключа, а область действия - это тип
Ответ 4
- @JsonManagedReference → Управляет прямой частью ссылки, а поля, помеченные этой аннотацией, - это те, которые получают Serialized
- @JsonBackReference → Управляет обратной частью ссылки, а поля/коллекции, помеченные этой аннотацией, не сериализуются.
Случай использования: У вас есть отношения "один-много или много-много" в ваших сущностях/таблицах, а не использование приведенного выше приведет к ошибкам, например,
Infinite Recursion and hence stackoverflow - > Could not write content: Infinite recursion (StackOverflowError)
Вышеупомянутые ошибки возникают из-за того, что Джексон (или другой похожий) пытается сериализовать оба конца отношения и заканчивается рекурсией.
@JsonIgnore выполняет аналогичные функции, но вышеупомянутые аннотации предпочтительнее.
Ответ 5
Как пишет Раджат Верма, его решение работает отлично. Спасибо человек, ты сэкономил мне много времени и гнева :-)
Важная часть:
Вам нужно определить поля какList
, у меня это было какSet
ранее, и это решение НЕ РАБОТАЕТ (выглядит как бесконечный цикл)!
Я добавляю свое решение:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
public class Agent {
@ManyToMany(mappedBy = "subscribers")
@ApiModelProperty(dataType = "List", example = "[1,2,3]") // for Swagger
@JsonIdentityReference(alwaysAsId = true) // show only id of Topic
private final List<Topic> subscribeTopics = new ArrayList<>()
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
public class Topic {
@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinTable(name = "topic_agent",
joinColumns = @JoinColumn(name = "fk_topic_id"),
inverseJoinColumns = @JoinColumn(name = "fk_agent_id"))
@ApiModelProperty(dataType = "List", example = "[1,2,3]")
@JsonIdentityReference(alwaysAsId = true)
private final List<Agent> subscribers = new ArrayList<>();
}