2008-11-30 70 views
5

我一直面臨着這樣的問題,即,在系列化休眠對象產生一個包含從休眠的所有改動的代碼unexpect個XML Hibernate的對象。問題與採用序列化的XStream

在序列化對象之前,我們對對象進行了一些清理。

但是,是否有標準選項可用於直接序列化對象?

+0

也許你可以顯示XML的樣子? – 2008-11-30 13:45:42

回答

3

我以前沒使用XStream的,但我已經系列化的Hibernate管理的實體。這並不好玩。

有兩個大問題:

  • 延遲加載;
  • 一對多關係。

前者是顯而易見的 - 你需要實際的數據序列化。後者則不那麼簡單 - 您聲明的針對集合接口的任何一對多關係(例如:Set<T>)將被Hibernate自己的(不可序列化的!)集合實現所堵塞。這很可能是Hibernate的類滲透到對象中的地方。

我最後寫的是這樣做反射代碼(實際上內省):

  1. 隨着會議開幕,感動了整個對象圖以強制加載卸載任何實體;
  2. 關閉Hibernate會話(包括涉及其連接的任何事務);
  3. 走過對象圖,用ArrayList,HashSet或HashMap(已知序列化集合)的實例替換任何列表,集合或映射。

需要注意的是第2步是很重要的 - 如果你更換集合在會議閉幕前,Hibernate會只是把自己的藏品右後衛在近...

編輯: @ cliff.meyers發現了一個我忘記提到的實現細節:如果你這樣做,你需要限制對象圖形走到你自己的實體,並觀察循環引用路徑(例如:通過緩存對你已經走過的對象的引用)。

1

有這個(和示例代碼)的一些信息了在Codehaus的JIRA:

http://jira.codehaus.org/browse/XSTR-226

我們寫了一些工具來解決這類問題對於很多其他的遠程實現(軸1,Blaze DS等)。我們所做的與Dan的解決方案非常相似,不過我們增加了聲明哪些對象路徑可以行走以及哪些可以「剪輯」的能力,因爲在很多情況下,我們對所有數據都不感興趣;它也會導致嚴重的問題發生數千次的「n + 1選擇」問題! :)我認爲實現一個XStream轉換器將是最佳的方法,因爲你只需要走一次對象圖。如果你在會話中設置了FlushMode.MANUAL,那麼你應該也可以在沒有Hibernate的情況下修改對象圖。因爲這是一種先進的技術,所以請謹慎使用。

+0

哎呀,忘了最初提到限制對象類型下降到(你的snip語法) - 感謝您的更正... – 2008-11-30 19:58:11

3

我想出了一些足夠的解決方案。在我的應用程序中,只有PersistentSets搞亂了XStream生成的XML。所以我增加了一個轉換到XStream的(這與開放Hibernate的Session和活動對象運行):

XStream xs = new XStream(); 
xs.registerConverter(new CollectionConverter(xs.getMapper()) { 
    @Override 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     org.hibernate.collection.PersistentSet ps = (PersistentSet) source; 
     super.marshal(new HashSet(ps), writer, context); 
    } 

    @Override 
    public boolean canConvert(Class type) { 
     return type.isAssignableFrom(org.hibernate.collection.PersistentSet.class); 
    } 
}, XStream.PRIORITY_VERY_HIGH); 
String s = xs.toXML(processInstance); 

序列化的XML看起來象下面這樣:

<processLogs class="org.hibernate.collection.PersistentSet"> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>813017</id> 
     <entryDate> 
     <time>1310832421216</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Wydrukuj wniosek</additionalInfo> 
     <logValue>GENERATE_APPLICATION</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[8]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>808211</id> 
     <entryDate> 
     <time>1310828206169</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Zaakceptuj</additionalInfo> 
     <logValue>ACCEPT</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[4]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 

在我的情況下,類屬性是不重要的,所以我忽略了它的價值。你當然可以修補它。

+0

+1非常有用,謝謝!我的下一個問題是一個PersistentSet包裝在一個UnmodifiableSet中,令人討厭的是,它不是一個可見的類: -/ – Rup 2011-09-20 10:32:04

1

還沒有使用它,但xstream-for-beans似乎適合(引用):

該項目提供實施映射器和轉換器,增強的XStream在以下幾個方面:

  1. 對象序列化,因爲他們被吸氣和暴露者暴露。可用於字段的XStream功能適用於爲getter/setter屬性定義的屬性。
  2. 清理序列化管理對象:自動省略無關字段和類 信息。
  3. 處理「離線」字段和代理對象。

我寫了一次定製的XStream Converter s到處理這個問題,作爲一個閉源項目不幸的一部分。 xstream-for-beans處理同樣的問題,非常值得一試。

我過去成功地使用了Terracotta的Pojoizer實用程序,但我認爲它不再被維護。