当前位置: 首页 > 知识库问答 >
问题:

单事务中的Spring批处理tasklet

邵俊才
2023-03-14

我使用FlatFileItemReader创建了一个spring批处理作业,它从一个分隔文件中读取数据,然后使用JdbcBatchItemWriter写入DB。我的setp配置如下所示。

<batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="fileReader" 
                writer="dbWriter" commit-interval="100">
            </batch:chunk>
        </batch:tasklet>
</batch:step>

上面的配置是为每100行打开单独的事务,因此,如果在完成tasklet(步骤1)之前发生故障,则我无法恢复之前提交的行。有没有办法在一个事务中运行整个tasklet?。

另外:我使用MapJobRepositoryFactoryBean作为作业存储库,不想在数据库中创建元表以重新启动。

共有2个答案

龙正初
2023-03-14

在Spring批处理中,作业一次总是只有一个事务。

请注意下图,因为我们可以看到事务在步骤开始时打开,并在步骤结束时提交。

图片来源

事实上,使用Spring批处理的主要优点之一是我们作为开发人员不必担心事务管理。即使出现故障,它也会自动回滚整个未提交的事务。

钮长恨
2023-03-14

(我上次使用Spring Batch已经有一段时间了,我希望我的理解仍然有效:P)不使用面向chuck的tasklet,只需创建一个简单的tasklet即可。默认情况下,一个简单的tasklet将在单个事务中运行。考虑到您已经构建了reader和writer,您可以编写一个tasklet,它模仿面向chuck的步骤(只是向您展示想法的伪代码):

public class ReaderWriterTasklet<T> implements Tasklet {
    private ItemReader<T> reader;
    private ItemWriter<T> writer;
    // and corresponding setters

    public RepeatStatus execute(StepContribution contribution,
                     ChunkContext chunkContext) {
        List<T> chunk = new LinkedList<T>();
        while (true) {
            T item = reader.read();
            if (item == null) {
                break;
            } else {
                chunk.add(item);
            }
        }
        writer.write(chunk);
        return RepeatStatus.FINISHED;
    }
}

(我相信你应该已经知道如何定义运行tasklet的步骤了,对吧?那我就跳过它)

另一种肮脏的方法是继续使用块,并将提交间隔设置为整数。MAX_VALUE。通过这样做,面向块的步骤将继续从读取器获取项目,直到它到达末尾,并在一个大块中写入写入器,这一切都发生在1个事务中。

 类似资料:
  • 在happy path场景中,我有一个spring批处理工作,但现在我将重点放在错误处理上。 但是,在另一个测试中,我想证明一个不可预见的数据库错误会导致作业失败。为此,我创建了一个触发器,该触发器会导致对要插入的表的插入失败。 这似乎起作用了,在writer执行之后,在事务提交期间抛出异常,并且我得到以下日志消息: 这似乎也是预期的行为。问题是,这并不能阻止工作。该步骤退出到SimplyRetr

  • 我有一个带有两个数据库的Spring Batch应用程序:一个SQLDB用于Spring Batch元数据,另一个是存储所有业务数据的MongoDB。关系DB仍然使用。但是我不认为Mongo写入是在带有回滚的活动事务中完成的。以下是上官方Spring Batch留档的摘录: ItemWriter实现,使用Spring数据的MongoOperations实现写入MongoDB存储。由于MongoDB

  • 我想了解Spring Batch是如何进行事务管理的。这不是一个技术问题,而是一个概念性的问题:Spring Batch使用什么方法?这种方法的后果是什么? 让我试着澄清一下这个问题。例如,在TaskletStep中,我看到步骤执行通常如下所示: 准备步骤元数据的几个JobRepository事务 每一块要处理的业务事务 更多JobRepository事务,用区块处理的结果更新步骤元数据 这似乎是

  • 我在批处理作业中使用多线程步骤来处理来自源数据库的记录并写入目标数据库。该步骤基于块,由JdbcpagingItemReader、Processor和JDBCBathItemWriter组成。我明白,如果在步骤处理期间发生任何异常,数据库事务将回滚整个块。我想了解一下Spring batch在内部是如何管理的?由于这是多线程步骤,因此不能保证处理器和写入器在块的同一线程中执行。块可能由不同的线程处

  • 事务在Spring批处理中未回滚。我有意抛出异常来测试事务回滚。即使从项目编写器引发异常,数据库事务也在提交。下面是写入器中保存到DB中的方法。对象是注入到此类中的 jpa 存储库 我尝试用@Transactional(传播=Propagation.REQUIRES_NEW, rollbackFor=Exception.class)标记上述方法的事务,但它仍然在提交事务。我肯定我错过了一些东西。任