JsonManagedReference против JsonBackReference
Я хотел бы знать разницу между @JsonManagedReference
а также @JsonBackReference
в Джексоне?
4 ответа
@JsonManagedReference - это передняя часть ссылки, которая обычно сериализуется. @JsonBackReference является задней частью ссылки - она будет исключена из сериализации.
Так что они действительно зависят от направления ваших отношений
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;
}
- @JsonManagedReference -> Управляет передней частью ссылки, и поля, отмеченные этой аннотацией, становятся сериализованными.
- @JsonBackReference -> Управляет обратной частью ссылки, а поля / коллекции, отмеченные этой аннотацией, не сериализуются.
Вариант использования: у вас есть отношения один-много или много-много в ваших сущностях / таблицах, и если вы не используете вышеперечисленное, это приведет к таким ошибкам, как
Infinite Recursion and hence stackru - > Could not write content: Infinite recursion (StackruError)
Вышеуказанные ошибки происходят из-за того, что Джексон (или что-то подобное) пытается сериализовать оба конца отношений и заканчивается рекурсией.
@JsonIgnore выполняет аналогичные функции, но вышеупомянутые аннотации предпочтительнее.
я предпочитаю@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
где свойство - это имя поля первичного ключа, а область действия - его тип.
Как пишет Раджат Верма, его решение работает отлично. Спасибо человек, ты сэкономил мне много времени и гнева:-)
Важная часть:
Вам нужно определить поля какList
Я имел это какSet
до и это решение НЕ РАБОТАЕТ (выглядит как бесконечный цикл)!
Я добавляю свое решение:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)
public class Agent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@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 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@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<>();
}
@JsonManagedReference
а также @JsonBackReference
предназначены для обработки этой двусторонней связи между полями, одно для родительской роли, другое для дочерней роли.
Чтобы избежать этой проблемы, связывание обрабатывается так, что свойство, аннотированное аннотацией @JsonManagedReference, обрабатывается нормально (обычно сериализуется, без специальной обработки для десериализации), а свойство, аннотированное аннотацией @JsonBackReference, не сериализуется; и во время десериализации его значение устанавливается равным экземпляру, который имеет "управляемую" (прямую) ссылку.