JsonManagedReference vs JsonBackReference

Я хотел бы узнать разницу между @JsonManagedReference и @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<>();
 }