加快使用Mule 3.5将DB select转换为XML

时间:2015-07-20 13:55:36

标签: mule

我正在尝试将数据从数据库查询转换为XML。大约有20,000行。运行需要十分钟,这对我来说似乎过于缓慢。

我注意到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"而数据库选择streaming="true",但是当我这样做时,我进入的迭代器我的有效负载从false返回hasNext(),而next()会抛出关闭的异常。

修改:更正了调用getOutputStream的结果。

1 个答案:

答案 0 :(得分:0)

问题是你正在尝试加载一个对内存来说不合理的XML(通过使用dom),你遇到的10分钟可能花费在垃圾收集中,所以最重要的是要做的事情。改进这是为了向wrapper.conf添加更多堆,只有当进程在非常低的负载下运行时才能这样做。

我建议您尝试分而治之的技巧,也许可以将您的磁盘用作中间存储。

您可以使用stax来传输XML

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