Mule DB数据检索成块

时间:2017-07-06 05:22:05

标签: mule mule-studio mule-component anypoint-studio mule-el

我们正试图提取约。来自数据库的40 GB数据,并希望生成多个csv文件。我们以流式方式使用mule DB连接器,它返回'ResultSetIterator'

Q1)如何将此ResultSetIterator转换为arraylist?或我们可以进一步用于生成文件的任何可读格式

Q2)我们尝试使用For-Each组件将这些数据拆分成块,它用于有限的数据集和用于提供SerializationException的大量数据

在下面的输入摘录中,我们使用for-each制作数据块并将其提供给多个文件的批处理

  <batch:job name="testBatchWithDBOutside">
        <batch:input>
            <logger message="#[payload]" level="INFO" doc:name="Logger"/>
        </batch:input>
        <batch:process-records>
            <batch:step name="Batch_Step">
                <batch:commit size="10" doc:name="Batch Commit">
                    <object-to-string-transformer doc:name="Object to String"/>
                    <logger message="#[payload]" level="INFO" doc:name="Logger"/>
                    <file:outbound-endpoint path="C:\output" outputPattern="#[message.id].txt" responseTimeout="10000" doc:name="File"/>
                </batch:commit>
            </batch:step>
        </batch:process-records>
    </batch:job>
    <flow name="testBatchWithDBOutsideFlow" processingStrategy="synchronous">
        <file:inbound-endpoint path="C:\input" responseTimeout="10000" doc:name="File"/>
        <db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10" doc:name="Database">
            <db:parameterized-query><![CDATA[select * from classicmodels]]></db:parameterized-query>
        </db:select>
        <foreach batchSize="5" doc:name="For Each">
            <batch:execute name="testBatchWithDBOutside" doc:name="testBatchWithDBOutside"/>
        </foreach>
    </flow>

3 个答案:

答案 0 :(得分:0)

Q1。您不希望将Iterator转换为List,因为这会破坏从DB连接器流式传输的目的并将所有记录加载到内存中。无论如何,Mule以相同的方式处理迭代器和列表。

Q2。批处理模块意味着for-each操作。 batch的输出:input必须是List或Iterator。你应该能够简化这个

<batch:job name="testBatch">
    <batch:input>
        <db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10" doc:name="Database">
            <db:parameterized-query><![CDATA[select * from classicmodels]]></db:parameterized-query>
        </db:select>
    </batch:input>
    <batch:process-records>
        <batch:step name="Batch_Step">
            <object-to-string-transformer doc:name="Object to String"/>
            <file:outbound-endpoint path="C:\output" outputPattern="#[message.id].txt" responseTimeout="10000" doc:name="File"/>
        </batch:step>
    </batch:process-records>
</batch:job>

您还需要使用转换数据库记录的组件替换object-to-string-transformer(此时的有效负载将是一个映射,其中键是列名,值是记录值)进入csv线。

您可以在Mule博客中找到一个不错的例子:https://blogs.mulesoft.com/dev/anypoint-platform-dev/batch-module-reloaded/

另一个选择是删除批处理器并使用DataWeave生成csv输出并将其流式传输到文件。这可能会有所帮助:https://docs.mulesoft.com/mule-user-guide/v/3.7/dataweave-streaming

Dataweave会在处理每条记录时调用ResultSetIterator上的next,并且Iterator将处理从底层数据库中选择记录块,因此步骤之间没有排队,或者将完整数据集加载到内存中。

<flow name="batchtestFlow">
    <http:listener config-ref="HTTP_Listener_Configuration" path="/batch" allowedMethods="GET" doc:name="HTTP"/>
    <db:select config-ref="Generic_Database_Configuration" streaming="true" doc:name="Database">
        <db:parameterized-query><![CDATA[select * from Employees]]></db:parameterized-query>
    </db:select>
    <dw:transform-message doc:name="Transform Message">
        <dw:set-payload><![CDATA[%dw 1.0
            %input payload application/java
            %output application/csv streaming=true, header=true, quoteValues=true
            ---
            payload map ((e, i) -> {
                surname: e.SURNAME,
                firstname: e.FIRST_NAME
            })]]></dw:set-payload>
    </dw:transform-message>
    <file:outbound-endpoint path="C:/tmp" outputPattern="testbatchfile.csv" connector-ref="File" responseTimeout="10000" doc:name="File"/>
</flow>

答案 1 :(得分:0)

您想使用OutputHander。确保你打开了流媒体然后使用脚本组件,例如选择groovy并一次处理一行,如下所示:

// script.groovy
return {evt, out ->

 payload.each { row ->
  out << row.SOMECOLUMN....  }

} as OutputHandler

xml中的组件

    <scripting:transformer returnClass="TODO" doc:name="ScriptComponent">
        <scripting:script engine="Groovy" file="script.groovy" />
    </scripting:transformer>

如果要返回一些输出。但是,如果您要在您的情况下写入文件,则不会使用变量out,而是写入您的文件。

答案 2 :(得分:0)

我找到了一种简单快捷的方法,如下所示:

此处DB连接器处于流式传输模式,For-Each正在按给定的批量大小

拆分记录
<flow name="testFlow" processingStrategy="synchronous">
        <composite-source doc:name="Composite Source">
            <quartz:inbound-endpoint jobName="test" cronExpression="0 48 13 1/1 * ? *" repeatInterval="0" connector-ref="Quartz" responseTimeout="10000" doc:name="Quartz">
                <quartz:event-generator-job/>
            </quartz:inbound-endpoint>
            <http:listener config-ref="HTTP_Listener_Configuration" path="/hit" doc:name="HTTP"/>
        </composite-source>
        <db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10000" doc:name="Database">
            <db:parameterized-query><![CDATA[SELECT * FROM tblName]]></db:parameterized-query>
        </db:select>
         <foreach batchSize="10000" doc:name="For Each">

                    <dw:transform-message doc:name="Transform Message">
                                           <dw:set-payload><![CDATA[%dw 1.0
                   %output application/csv
                   ---
                   payload map {
                    field1:$.InterfaceId,
                    field2:$.Component

                   }]]></dw:set-payload>
                    </dw:transform-message>
               <file:outbound-endpoint path="F:\output" outputPattern="#[message.id].csv" responseTimeout="10000" doc:name="File"/>
        </foreach>
        <set-payload value="*** Success ***" doc:name="Set Payload"/>

    </flow>