Spring Batch从数据库读取一次,写入另一个数据库并写入CSV

时间:2017-05-16 16:26:20

标签: spring spring-batch

我是Spring Batch的新手,并尝试在

中实现批处理作业
  1. 从MySQL数据库中读取
  2. 将结果写入CSV文件
  3. 对MySQL结果集进行一些处理并写入另一个数据库。
  4. 我查看了this question on StackOverflow,但主要接受的答案主要是实现两个从数据库中读取两次的步骤:

    <job id="myJob">
        <step id="step1" next="step2">
            <tasklet>
                <chunk reader="reader" writer="typeAwriter"/>
            </tasklet>
        </step>
        <step id="step2">
            <tasklet>
                <chunk reader="reader" processor="processor" writer="typeBwriter"/>
            </tasklet>
        </step>
    </job>
    

    除了从MySQL数据库中读取两次之外,还没有更有效的方法吗?例如,如果查询非常大并且拖累系统性能怎么办?

2 个答案:

答案 0 :(得分:2)

您需要的是块策略而不是tasklet。 ItemReader将从您的数据库中读取块,处理器将处理您的数据,然后您可以将每个项目发送到可以写入数据库和文件的ItemWriter。这是许多可能的策略之一,我不知道您的业务逻辑的详细信息,但我认为这些信息足以让您按照自己的想法进行操作。

<?xml version="1.0" encoding="UTF-8"?>
<job id="customerJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd"
version="1.0">

    <step id="step1">
        <chunk item-count="5">
            <reader ref="itemReader"/>
            <processor ref="itemProcessor"/>
            <writer ref="itemWriter"/>
        </chunk>
    </step>
</job>

这是JSR-352 XML类型,对于Spring,你有相应的方法。

答案 1 :(得分:0)

我会继续回答我自己的问题。有多种方法可以做到这一点,但我发现首先将属性和对象保存到StepExecutionContext,然后在步骤完成后将它们提升到JobExecutionContext。它也非常详尽地记录here.

第1步:

在你的作家/读者中声明私人StepExecution。然后,在您的读/写方法内创建步骤上下文,并将您的数据作为键/值对放入:

ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("someKey", someObject);

第2步: 在步骤的bean配置中添加ExecutionContextPromotionListenerExecutionContextPromotionListener必须包含名为Keys的String[]属性,其中包含您希望在步骤之外提升到作业范围的键,类似于LinkedIn article中的此实现:

@Bean
public ExecutionContextPromotionListener promotionListener() {
    ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
    listener.setKeys( new String[] { "entityRef" } );
    return listener;
}

第3步: 您还需要在执行步骤之前将StepExecution添加到Writer中:

@BeforeStep
public void saveStepExecution( StepExecution stepExecution ) {
    this.stepExecution = stepExecution;
} 

第4步: 这将为您的write()方法提供对stepExecution实例的访问权限,在该实例中,您可以访问stepContext以保存数据。例如,你可以写

write() {
    ... // write logic

    ExecutionContext stepContext = this.stepExecution.getExecutionContext();
    stepContext.put("keyYouWantToPutIn", theCorrespondingDataObject);
}

最后,在下一步中,您可以检索此数据(例如直接来自Spring Batch documentation

@BeforeStep
public void retrieveInterstepData(StepExecution stepExecution) {
    JobExecution jobExecution = stepExecution.getJobExecution();
    ExecutionContext jobContext = jobExecution.getExecutionContext();
    this.someObject = jobContext.get("someKey");
}

但是,这一次,请注意它是从jobContext而不是stepContext访问的 - 它已被提升!