【FastJSON】解決FastJson中「$ref 循環引用」的問題

【需求與環境描述】前端

0、開發環境java

  SSH,EasyUI,MySQL 數據庫

一、需求要求:json

  (1)首先獲取全部的貸款訂單數據,即List <LoanOrder>。瀏覽器

  (2)而後從單個貸款訂單實體LoanOrder去訪問貸款人實體Loaner的信息。 服務器

二、實體之間的關係描述app

  (1)LoanOrder實體與Loaner實體是雙向的多對一和一對多關係。fetch

  (2)LoanOrder是「多方」,其中的關係屬性爲「private Loaner loaner」。this

  (3)Loaner是「一方」,其中的關係屬性爲「Set<LoanOrder> orders」。 spa

三、代碼示例

  (1) 貸款訂單LoanOrder代碼

@Entity
@Table(name = "t_bp_loan_order")
public class LoanOrder implements java.io.Serializable {
	
	/*省略其餘次要屬性*/
	private Loaner loaner;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "LOANER_ID")
	public Loaner getLoaner() {
		return this.loaner;
	}
}

  (2) Loaner方代碼

@Entity
@Table(name = "t_bp_loaner")
public class Loaner implements java.io.Serializable {

	/* 其餘普通屬性略去 */
	private Set<LoanOrder> loanOrders = new HashSet<LoanOrder>(0);

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "loaner")
	@JSONField(serialize = true)
	public Set<LoanOrder> getLoanOrders() {
		return this.loanOrders;
	}
}

 

【障礙再現】

一、需求01:

首先獲取全部的貸款訂單數據,即List <LoanOrder>,發現貸款人「張三」有兩個訂單。

 

二、需求02:

  而後,依次在第一個和第二個貸款訂單中點擊「張三」,從而去訪問「名字叫作‘張三’」貸款人實體Loaner的信息。

結果,第一個訂單能夠顯示貸款人的數據,可是在第二個訂單數據中,不能獲取到「loaner(貸款人)」的數據,而且loaner中提示「$ref」。

通過兩次點擊後,服務器後臺傳送到前臺頁面上的JSON數據以下所示:

 

【解決方案】

第一步:禁用FastJson的「循環引用檢測」特性。

一、核心代碼

 

二、做用

決定了生成的「多個」JSON對象中,是否加載被引用的同一個對象的數據。

在此,決定了生成的「多個」貸款訂單JSON對象中,是否加載被引用的同一個貸款人JSON對象的數據。

 

三、開啓和關閉FastJson的「循環引用檢測」特性的對比

 

當從服務器端傳來的多個LoanOrder對象經過FASTJSON被序列化到「前端」後,會被瀏覽器解析成「DOM」對象。 

(1) 開啓FastJson的「循環引用檢測」特性時:

1對於第一個LoanOrder 01,fastjson會徹底解析並加載它的全部數據,包括它所關聯的Loaner貸款人信息,以下圖所示。

 

2 對於第二個LoanOrder 02,fastjson僅僅解析並加載其貸款訂單部分的數據,對於「$ref」所指向的 Loaner貸款人的數據,fastjson會由於「開啓了fastJson的‘循環引用檢測’機制」而不去加載該貸款人數據。

當加載第二個貸款訂單數據時,fastjson檢測到已經在第一個訂單LoanOrder 01中加載了「貸款人Loaner」的數據,fastjson會由於「開啓了‘循環引用檢測’機制」而不去再次加載該貸款人數據,而僅僅將一個指向第一個貸款訂單LoanOrder01中「貸款人」的引用賦值給第二個貸款訂單中的貸款人的位置。

所以,在生成的第二個貸款訂單的JSON串中,對於貸款人信息,僅僅只有一個「$ref」。

而jQuery這個前端技術又沒法解析該引用,所以,就沒法讀取貸款人的數據,以下圖所示。

 

第二步禁止Loaner對象獲取Set<LoanOrder>的數據。

方法一:將原來的「雙向關係」修改成「單向關係」

一、原來:LoanOrder與Loaner之間是雙向關係。

二、修改後:只能從LoanOrder訪問Loaner,從Loaner沒法訪問到LoanOrder。

三、具體方法01

       重要前提:不刪除Loaner中的「Set<LoanOrder> orders」屬性。

  注意,若在採用註解映射實體類的方式中,沒有使用「@Transient」註解,則數據庫會報錯。

四、具體方法02

       直接刪除「Set<LoanOrder> orders」屬性極其相關的setter()和getter()方法。

      

方法二:不修改關係的前提下,禁止序列化

在不修改LoanOrder和Loaner雙向關係的狀況下,Loaner對象中的Set<LoanOrder>集合完成數據的加載,當其向前端Browser傳遞JSON數據時,禁止序列化Set<LoanOrder>集合。

具體方法:

設置註解「@JSONField(serialize = false)」。

說明:

A.「@JSONField」是fastjson提供的註解標籤,其做用爲控制其所標註的屬性「可否被序列化」。

B.在此其做用爲:禁止"loanOrders"這個Set集合被序列化。

具體以下圖所示。

 

 

【解決後的效果】 

 

讀者如要轉載,請標明出處和做者名,謝謝。
地址01:http://space.itpub.net/25851087
地址02:http://www.cnblogs.com/zjrodger

做者名:zjrodger  

相關文章
相關標籤/搜索