Java 为什么杰克逊';s PropertyGenerator防止递归循环

Java 为什么杰克逊';s PropertyGenerator防止递归循环,java,json,rest,jackson,jax-rs,Java,Json,Rest,Jackson,Jax Rs,我有两个双向映射的实体。一种车辆,具有一系列登记和登记本身。这些实体作为REST服务公开 @Entity @XmlRootElement public class Vehicle implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String brand; private String type; @One

我有两个双向映射的实体。一种车辆,具有一系列登记和登记本身。这些实体作为REST服务公开

@Entity
@XmlRootElement
public class Vehicle implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String brand;
  private String type;

  @OneToMany(mappedBy = "vehicle", fetch = FetchType.EAGER)
  private List<Registration> registrations;
}
经过一些研究,我发现我必须将注释@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class,property=“id”)添加到Vehicle类以解决问题


我的问题是:PropertyGenerator类实际上做什么?

问题不是因为
FetchType.EAGER
FetchType.EAGER
是一个JPA注释,当您使用Jackson序列化Vehicle实例时,它不会起作用

实际上,Jackson正在序列化一辆车,这会触发注册列表的序列化,这会序列化一辆车,它有一个注册列表,以此类推

正如您所注意到的,
@JsonIdentityInfo
注释缩短了无限递归,但这不是因为您指定了特定的
属性生成器。
@JsonIdentityInfo
的JavaDoc提供了一些关于发生了什么的见解:

@JsonIdentityInfo注释,用于指示注释类型或属性的值应序列化,以便实例包含其他对象标识符(除实际对象属性外),或作为引用,该引用由引用完整序列化的对象id组成。实际上,这是通过将第一个实例序列化为完整对象和对象标识,并将对该对象的其他引用序列化为引用值来实现的

换句话说,第一次序列化某些内容时,您将获得完整的序列化JSON/XML版本。下次序列化该对象时,您将获得对第一个序列化对象的引用

还有其他方法可以解决这个问题。检查(你的问题可以说是这个问题的重复)。这里的答案建议您也可以使用
@JsonIgnore
@JsonManagedReference
@JsonBackReference
的组合来避免无限递归

现在,关于
PropertyGenerator
的实际功能,请回答以下特定问题:它指示Jackson使用类中的特定属性作为对象完整序列化版本的引用。您将“id”指定为属性,因此在生成的序列化JSON/XML中,您应该看到,如果您有一个id为342的对象,那么第一个序列化对象将显示该id和所有其他序列化属性,但随后每次序列化该对象时,您只会看到342序列化为对原始对象的引用

@Entity
@XmlRootElement
public class Registration implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;

  @ManyToOne
  private Vehicle vehicle;
}