2015-10-26 91 views
4

我有兩個實體,其是雙向映射。擁有註冊和註冊本身的車輛。這些實體作爲REST服務公開。爲什麼傑克遜的PropertyGenerator防止遞歸循環

@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; 
} 

的問題是,所述FetchType.EAGER產生無限遞歸

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

    private String name; 

    @ManyToOne 
    private Vehicle vehicle; 
} 

一些研發我想通了,我必須添加註釋@JsonIdentityInfo後(發電機= ObjectIdGenerators.PropertyGenerator.class,財產=「ID」)到車輛類來解決這個問題。

我的問題是:什麼是PropertyGenerator類實際上呢?

回答

4

問題是FetchType.EAGER不是因爲。 FetchType.EAGER是JPA註釋,當您使用Jackson序列化Vehicle實例時不會發揮作用。

什麼實際發生的是,傑克遜被序列化的車輛,這將觸發註冊的名單,其中序列化的車輛,其中有寄存的名單序列,依此類推,直到永遠。

正如您注意到的那樣,@JsonIdentityInfo註釋將無限遞歸短路,但這不是因爲您指定的具體PropertyGenerator。爲@JsonIdentityInfo的JavaDoc給出了一些洞察到這是怎麼回事:

@JsonIdentityInfo用於指示註釋,註釋類型或屬性的值應該是序列化,這樣無論是包含其他對象標識符(除了實際的對象屬性實例),或者作爲由引用完整序列化的對象ID組成的引用。實際上,這是通過將第一個實例序列化爲完整對象和對象標識以及對該對象的其他引用作爲參考值來完成的。

換句話說,當您第一次序列化某些東西時,您將獲得完整的序列化JSON/XML版本。下次該對象被序列化時,您將獲得對該第一個序列化對象的引用。

還有其他的方法過於解決這個問題。看看Infinite Recursion with Jackson JSON and Hibernate JPA issue(你的問題可以說是這一個的重複)。這些問題的答案有建議你也可以使用@JsonIgnore@JsonManagedReference組合和@JsonBackReference避免無限遞歸。

現在,對於您的具體問題PropertyGenerator實際上做了什麼:它指示傑克遜使用您的類中的特定屬性作爲對象的完整序列化版本的引用。您將「id」指定爲屬性,因此在您的結果序列化JSON/XML中,您應該看到如果您有一個ID爲342的對象,則第一個序列化對象將顯示該ID和所有其他序列化屬性,但是隨後每個對象序列化你只會看到342序列化爲原始對象的引用。