Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring batch 将CompletionPolicy扩展为从MultiResourceItemReader完成/提交每个资源_Spring Batch - Fatal编程技术网

Spring batch 将CompletionPolicy扩展为从MultiResourceItemReader完成/提交每个资源

Spring batch 将CompletionPolicy扩展为从MultiResourceItemReader完成/提交每个资源,spring-batch,Spring Batch,我的问题是我不理解各种spring批处理上下文。参考文档解释了如何将数据传递给未来的步骤。但是如何在一个步骤内在读写器组件之间传递数据呢。步骤上下文。是否存在块上下文? 我以前在编写分区程序时使用过before执行上下文。但这些都是并行执行的 我现在需要做一个有序的操作。它基本上是一个jdbc导入作业,但每个文件都需要提交,否则它们就是外键约束 在MultiResourceItemReader委托给ItemReader之前,我能够获取单个文件资源的行数的最简单位置是MultiResourceIt

我的问题是我不理解各种spring批处理上下文。参考文档解释了如何将数据传递给未来的步骤。但是如何在一个步骤内在读写器组件之间传递数据呢。步骤上下文。是否存在块上下文? 我以前在编写分区程序时使用过before执行上下文。但这些都是并行执行的

我现在需要做一个有序的操作。它基本上是一个jdbc导入作业,但每个文件都需要提交,否则它们就是外键约束

在MultiResourceItemReader委托给ItemReader之前,我能够获取单个文件资源的行数的最简单位置是MultiResourceItemReader。但是在查看了各种CompletionPolicy实现之后,它们似乎只能访问RepeatContext。如何将MultiResourceItemReader中的值存储在RepeatContext中,以便CompletionPolicy可以在特定文件资源行计数后访问并提交

举例说明如何扩展abstract CountingCompletionPolicy以及如何存储来自MultiResourceItemReader的数据将很有帮助

或者也许有更好的方法来评估这类工作

<!-- <job id="job" restartable="${restartable}" xmlns="http://www.springframework.org/schema/batch"> -->
    <batch:job id="job" restartable="true"
        xmlns="http://www.springframework.org/schema/batch">
        <batch:step id="step1-unzipFile">
            <batch:tasklet ref="unzipFileTasklet" />
            <batch:next on="COMPLETED" to="step2-import" />
        </batch:step>
        <batch:step id="step2-import"> <!-- we can't use a commit-interval="${commitInterval} cause it messes with 2nd pass import processing if the commit ends up being the middle of the file -->
            <batch:tasklet>
                <batch:chunk reader="multiResourceReader" writer="itemWriter" chunk-completion-policy="completionPolicy"/>  
            </batch:tasklet>
            <!-- <batch:next on="COMPLETED" to="step3-fileCleanUp" /> -->
        </batch:step>
        <!-- <batch:step id="step3-fileCleanUp">
            <batch:tasklet ref="fileCleanUpTasklet" />
        </batch:step> -->
    </batch:job>




    <bean id="multiResourceReader" class="springbatch.iimport.extended.SequentialLoaderMultiFileResourceItemReader" scope="step">
        <property name="resourceDirectoryPath" value="${importTempDirectoryBasePath}/#{jobParameters['jobKey']}/"/>
        <property name="delegate" ref="itemReader"/>
    </bean>

    <bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="lineMapper" ref="lineMapper" />
    </bean>

    <bean id="lineMapper" class="springbatch.iimport.extended.JsonToTupleLineMapper"/>

    <bean id="itemWriter" class="springbatch.iimport.extended.TupleJdbcBatchItemWriter" scope="step">
        <property name="moduleDataSource" ref="moduleDataSource"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="jobKey" value="#{jobParameters['jobKey']}"/>
        <property name="jobDef" value="#{jobParameters['jobDef']}"/>
    </bean>

    <bean id="completionPolicy" class="?"/> 

    <!-- tasklets -->

    <bean id="unzipFileTasklet" class="springbatch.iimport.tasklets.UnZipFile" scope="step">
        <!-- the temp directory the files are unzipped to end up being #{jobParameters['importZipFileName']} -->
        <property name="importZipFileName" value="${uploadDir}/#{jobParameters['importZipFileName']}" />
        <property name="jobKey" value="#{jobParameters['jobKey']}"/>
        <property name="importTempDirectoryBasePath" value="${importTempDirectoryBasePath}" />
     </bean>

您可以编写自己的
CompletionPolicy
,它前瞻
itemReader
(使用
peakableitemreader
)并在下次调用
itemReader时将当前区块返回为“已完成”。next()
返回
null
(表示当前文件的EOF)。
请记住:此解决方案可能会导致内存问题,因为内存中的文件内容已满

public class EOFCompletionPolicy extends CompletionPolicySupport
{
    private EOFCompletionContext cc;
    private PeekableItemReader<Object> reader;

    public void setReader(PeekableItemReader<Object> forseeingReader)
    {
        this.reader = forseeingReader;
    }

    @Override
    public boolean isComplete(RepeatContext context)
    {
        return this.cc.isComplete();
    }

    @Override
    public RepeatContext start(RepeatContext context)
    {
        this.cc = new EOFCompletionContext(context);
        return cc;
    }

    @Override
    public void update(RepeatContext context)
    {
        this.cc.update();
    }

    protected class EOFCompletionContext extends RepeatContextSupport
    {
        boolean eof = false;
        public EOFCompletionContext (RepeatContext context)
        {
            super(context);
        }

        public void update()
        {
            final Object next;
            try
            {
                next = reader.peek();
            }
            catch (Exception e)
            {
                throw new NonTransientResourceException("Unable to peek", e);
            }
            // EOF?
            this.eof = (next == null);
        }

        public boolean isComplete() {
            return this.eof;
        }
    }
}
公共类EOFCompletionPolicy扩展了CompletionPolicySupport
{
私人EOFCompletionContext cc;
私人偷看项目阅读器;
public void setReader(用于SeeingReader的PeakableItemReader)
{
this.reader=forseeeingreader;
}
@凌驾
公共布尔值isComplete(RepeatContext上下文)
{
返回此.cc.isComplete();
}
@凌驾
公共RepeatContext开始(RepeatContext上下文)
{
this.cc=新的EOFCompletionContext(上下文);
返回cc;
}
@凌驾
公共无效更新(重复上下文)
{
this.cc.update();
}
受保护类EOFCompletionContext扩展了RepeatContextSupport
{
布尔eof=假;
公共EOFCompletionContext(RepeatContext上下文)
{
超级(上下文);
}
公共无效更新()
{
下一步是最终目标;
尝试
{
next=reader.peek();
}
捕获(例外e)
{
抛出新的非TransientResourceException(“无法偷看”,e);
}
//EOF?
this.eof=(next==null);
}
公共布尔值isComplete(){
返回此.eof;
}
}
}

谢谢。文件中是否可能有提交间隔。有些文件可能包含数十万行。如果我混合使用SimpleCompletionPolicy功能和EOFCompletionPolicy功能,使当前块在达到chunkSize或EOF时返回为“已完成”。如果你能告诉我它是否可行,我会想出如何编写它。如果你想(并且你可以管理)你在上面的评论中写的内容,你应该能够使用基于提交间隔的标准完成策略(又称块大小的完成策略)来解决这个问题我将EOFCompletionPolicy.EOFCompletionContext.isComplete()中的布尔表达式与return(getStartedCount()>=chunkSize)| |(next==null)组合在一起;我只是不确定org.springframework.batch.item.support.SingleItemPeakableItemReader中的委托属性是什么。您能提供一个配置示例吗?好的,我在这里找到了一个示例:(感谢您的帮助)实际上,这种方法的问题是next==null在使用MultiResourceItemReader时并不表示单个文件资源的结束。虽然SingleItemPeakableItemReader应该包装MultiResourceItemReader,而不是它的委托