Kevin.Zhong

          彪悍的人生不需要解釋,彪悍的代碼不需要測試。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            17 隨筆 :: 12 文章 :: 14 評論 :: 0 Trackbacks

            在Java中的模型關系設計中,循環的關系是很常見的,特別是ORM的出現,關系的循環更加有利于維護各自的狀態。但就是這種循環的關系,在java對象序列化時,不可避免的會導致循環引用(Cycle Reference)的問題。


          導致CycleReference的情況

            
           還是舉個例子吧(代碼說話):一個很典型,很常見的雙向引用的對象關系。

           1@Entity
           2
           3public class Company{
           4
           5    @Id
           6
           7    @Column(.)
           8
           9    private String id;
          10
          11    @OneToMany(.)
          12
          13    private Set<Employee> employee = new HashSet<Employee>();
          14
          15    //setters/getters
          16
          17    
          18
          19}

          20
          21@Entity
          22
          23public class Employee{
          24
          25    @Id
          26
          27    @Column(.)
          28
          29    private String id;
          30
          31    @ManyToOne
          32
          33    private Company company;
          34
          35    //setters/getters
          36
          37    
          38
          39}

          40
          41


          另外一種導致這個問題的情況是,多個對象間關系形成一條回路,跟電學有點像。(具體就不舉例了,在模型設計時,最好還是避免出現這種情況。)

          導致這種問題的原因

          用jaxb(如果沒有特殊解釋,本文采用的都是jaxb)序列化Company時,無疑會發生循環引用。
          當序列化引擎解析Company時,它發現這個對象持有一個Employee的引用,轉而去騷擾Employee。解析Employee時,發現他又持有Company的引用,又轉回Company。如此問題產生。
          引擎它并不知道在遇到循環引用問題時,該怎么處理,它只是忠實得按照固定的算法去執行任務。所以我們得讓引擎聰明點,我們得讓引擎遇到這種問題有處理機制。

          解決問題

          既然需要引擎更聰明,那就沒辦法,就得燒香拜佛,希望制造商的產品擴展性足夠好,考慮了足夠多的情況。
          幸運的是,jaxb提供了有這種擴展。(CycleRecoverable接口)
          行軍打仗(例子先行):(將以上的例子改下)

           1@Entity
           2
           3public class Company implements CycleRecoverable{
           4
           5    @Id
           6
           7    @Column(.)
           8
           9    private String id;
          10
          11    @OneToMany(.)
          12
          13    private Set<Employee> employee = new HashSet<Employee>();
          14
          15    //當遇到循環引用時,用temp替代this,返給jaxb解析。
          16
          17    public Object onCycleDetected(Context arg0) {
          18
          19        Company temp = new Company ();
          20
          21        temp.setId(id);
          22
          23        return temp;
          24
          25    }

          26
          27    //setters/getters
          28
          29    
          30
          31}

          32
          33@Entity
          34
          35public class Employee implements CycleRecoverable{
          36
          37    @Id
          38
          39    @Column(.)
          40
          41    private String id;
          42
          43    @ManyToOne
          44
          45    private Company company;
          46
          47    public Object onCycleDetected(Context arg0) {
          48
          49        Employee temp = new Employee();
          50
          51        temp.setId(id);
          52
          53        return temp;
          54
          55    }

          56
          57  //setters/getters
          58
          59    
          60
          61}

          62
          63


          注意到onCycleDetected方法就是一個回調方法,當遇到循環引用時,jaxb引擎會調用這個方法,用return對象來替換this。所以在這個過程中,就可以將引起循環引用問題的關系斷開,返回給jaxb
          當然Company和Employee對象沒必要全部實現CycleRecoverable接口,但是拿到現實的模型圖中去,誰也保證不了他們不跟別的對象有循環的關系存在。因此還是建議大家把模型都實現這個接口,也好一勞永逸。

          希望大家得到了想要的東西。
          Thanks

          posted on 2009-01-05 11:17 Kevin.Zhong 閱讀(3018) 評論(4)  編輯  收藏 所屬分類: rest

          評論

          # re: java對象序列化所引起的循環引用的思考 2009-01-06 09:11 yeshucheng
          這個就是所謂的對象圖序列化吧  回復  更多評論
            

          # re: java對象序列化所引起的循環引用的思考 2009-01-06 09:16 Kevin.Zhong
          @yeshucheng
          是的,如果需要將模型推向前臺,序列化模型是很常見的做法。  回復  更多評論
            

          # re: java對象序列化所引起的循環引用的思考 2009-01-06 09:30 congdepeng@126.com

          我可以引用這句話嗎
          彪悍的人生不需要解釋,彪悍的代碼不需要注釋。
            回復  更多評論
            

          # re: java對象序列化所引起的循環引用的思考 2009-01-06 12:41 Kevin.Zhong
          @congdepeng@126.com
          我改了,彪悍的代碼不需要測試。哈哈。  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 荥经县| 浪卡子县| 合江县| 双江| 吴忠市| 白河县| 马山县| 陇川县| 琼结县| 丹巴县| 光泽县| 铁岭市| 台江县| 临沧市| 铜陵市| 孝义市| 城步| 新郑市| 南投市| 兴山县| 桓仁| 长岭县| 灵宝市| 保山市| 汽车| 阿尔山市| 广昌县| 焦作市| 仁化县| 南江县| 子长县| 西乌| 庄浪县| 略阳县| 扎囊县| 佛冈县| 全椒县| 日喀则市| 潮安县| 新民市| 石嘴山市|