2015-07-20 33 views
1

我試圖將數據庫查詢中的數據轉換爲XML。大約有20,000行。這需要運行10分鐘,這對我來說似乎過於緩慢。加速將數據庫查詢轉換爲XML使用Mule 3.5

我注意到eventContext有一個getOutputStream方法,但會引發異常,當我嘗試調用它時每當我調用它時都會返回null。我也沒有Java的專業知識來了解流式傳輸XML的最佳方式,但我確信我可以查看它,我很欣賞那裏的任何提示。

我想要的XML的結構是這樣的:

<myElements> 
    <myElement> 
     <someId>123454</someId> 
     <someProperty>Some Value</someProperty> 
     <mySubElements> 
      <mySubElement> 
       <anotherId>67890</anotherId> 
       <anotherProperty>Another Value</anotherProperty> 
      </mySubElement> 
      <mySubElement> 
       <anotherId>24680</anotherId> 
       <anotherProperty>Yet Another Value</anotherProperty> 
      </mySubElement> 
     </mySubElements> 
    </myElement> 
</myElements> 

我查詢的輸出是這樣的:

SOME_ID SOME_PROPERTY  ANOTHER_ID ANOTHER_PROPERTY 
12345  Some Value   67890   Another Value 
12345  Some Value   24680   Yet Another Value 

我使用component變壓器,和我的代碼看起來像這樣:

public Object onCall(MuleEventContext eventContext) throws Exception { 
    List queryResults = (List) eventContext.getMessage().getPayload(); 

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 

    // root elements 
    Document doc = docBuilder.newDocument(); 
    Element myElements = doc.createElement("myElements"); 
    doc.appendChild(myElements); 

    Element myElement = null; 
    Integer currentSomeId = null; 

    for (Integer i = 0; i < queryResults.size(); i++) 
    { 
     Map queryRow = (Map) queryResults.get(i); 
     if (!queryRow.get("SOME_ID").equals(currentSomeId)) 
     { 
      myElement = doc.createElement("myElement"); 
      /* populate my element, including with an empty mySubElements */ 
     } 

     Element mySubElement = doc.createElement("myElement"); 
     /* populate mySubElement */ 
    } 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    TransformerFactory tf = TransformerFactory.newInstance(); 
    Transformer t = tf.newTransformer(); 
    t.setOutputProperty(OutputKeys.INDENT, "yes"); 
    t.transform(new DOMSource(doc), new StreamResult(baos)); 
    eventContext.getMessage().setPayload(doc); 
    return baos.toByteArray(); 
} 

我的騾子流看起來像這樣:

<flow name="MyElementsFlow-Https"> 
    <http:listener config-ref="HTTP_Listener_Configuration" path="${webapi.myelements.path}" allowedMethods="GET" doc:name="HTTP"/> 
    <flow-ref name="MyElementsFlow" doc:name="Flow Reference"/> 
</flow> 

<flow name="MyElementsFlow" processingStrategy="synchronous"> 
    <db:select config-ref="DB-Connector" doc:name="Select"> 
     <db:template-query-ref name="select-template" /> 
    </db:select> 
    <component class="myJavaComponent" doc:name="To XML"/> 
</flow> 

編輯:我想我會嘗試的HTTP連接設置爲responseStreamingMode="ALWAYS"和DB選擇streaming="true",但是當我這樣做,我在有效載荷獲取迭代器返回從hasNext()false,並且next()拋出一個關於被關閉的異常。

編輯:更正後的致電getOutputStream的結果。

回答

0

問題是你正在試圖加載一個不合理的XML到內存中(通過使用dom),你正在經歷的10分鐘可能在垃圾收集中花費最多,所以要做的第一件小事爲了改善這一點,你需要在你的wrapper.conf文件中增加更多的堆,只有當進程運行在非常低的負載時,你才能做到這一點。

我建議你嘗試一種分而治之的技術,也許使用你的磁盤作爲中間存儲。

您可以使用STAX流式傳輸XML

https://docs.oracle.com/javase/tutorial/jaxp/stax/using.html

+0

謝謝,@Juan阿爾貝託·洛佩斯Cavall。我會試一試你的建議。你知道是否有一種方法可以將數據流直接傳輸到Mule的輸出流中,還是必須在最後寫入字節數組? –

+0

或者,您是否建議完全不使用有效負載機制,並告訴Mule從我寫入的磁盤加載XML文件,並將其放入字節數組中? –

+0

如果您返回一個xml流,那麼mule的xml模塊可以將它轉換爲可讀的內容,但您可能採取了各種方法。 –