【问题标题】:In a read-write chunk oriented process where does Spring Batch commit?在面向读写块的过程中,Spring Batch 在哪里提交?
【发布时间】:2019-01-09 22:19:35
【问题描述】:

在我的 java 项目中,我正在使用 Spring Boot 进行面向块的读取 (FlatFileItemReader) - 写入 (JdbcBatchItemWriter) 进程。使用HikariCp 数据源。

查看 Spring 批处理 jdbc 编写器,我们可以找到该部分:

               //some code
                @Override
                public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
                    for (T item : items) {
                        itemPreparedStatementSetter.setValues(item, ps);
                        ps.addBatch();
                    }
                    return ps.executeBatch();
                }
              //some code

所以基本上在这里,如果我的 Hikari 数据源的 setAutocommit 参数为 true,这意味着在 ps.executeBatch() 之后我的数据库将被更新。

这里的第一个问题,关于PreparedStatement.executeBatch() 它是如何处理的?它是提交每个 sql 语句还是在每个 sql 语句的末尾?

setAutocommit参数为false的情况下,ps.executeBatch()之后不应更新。

由于 Spring 批处理应该管理事务和提交。我试图找到它在哪里提交,以便更好地理解我遇到的问题。期待ChunkOrientedTaskletSimpleChunkProcessorTransactionTemplate我找不到它在提交过程中的哪个位置。

所以我的第二个问题是,Spring 批处理在面向块的过程中准确提交到哪里?

编辑:使用 Spring 批处理 3.0.7

EDIT :似乎在AbstractPlatformTransactionManager.processCommit(DefaultTransactionStatus status) 中处理,但仍然无法理解如何处理。

【问题讨论】:

    标签: java spring-batch commit spring-jdbc spring-transactions


    【解决方案1】:

    您的自动提交参数无关紧要,Spring 将管理事物并在它认为合适的时候覆盖它(并且它确实认为它合适)。

    您可以set the commit interval 定义您希望提交的频率。

    你是否应该改变它完全取决于你打算如何批处理,你的执行是否会失败,是否应该跳过或重试这些情况以及其他类似的事情。

    【讨论】:

    • 好吧,在我的情况下,参数自动提交为 true,数据库已更新,而为 false,尽管 Spring 应该管理它。我知道我可以设置块大小和提交间隔,我是通过StepBuilderFactory.get("myJob").<a,b>chunk(100).//stuff
    • 那么听起来您的所有设置都不正确。确保您的PlatformTransactionManager 配置正确,等等。
    • 那么我想不通是什么? @Autowired private ResourcelessTransactionManager resourcelessTransactionManager; @Bean public ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); }
    • 反正题主有点出格了
    • 一点也不。如果您查看ResourcelessTransactionManager,您会发现commit()rollback() 方法是无操作的。您使用了错误的管理器。
    【解决方案2】:

    关于“何时提交?”的问题,Spring Batch docs

    5.1 面向块的处理

    Spring Batch 在其最 共同实现。面向块的处理是指读取 一次一个数据,并创建将被写出的“块”, 在事务边界内。从 ItemReader 读入一项, 交给 ItemProcessor 并聚合。一旦物品数量 读取等于提交间隔,整个块通过 ItemWriter,然后事务被提交。

    下面是上述相同概念的代码表示:

    List items = new Arraylist();
    for(int i = 0; i < commitInterval; i++){
        Object item = itemReader.read()
        Object processedItem = itemProcessor.process(item);
        items.add(processedItem);
    }
    itemWriter.write(items);
    

    因此,如果您要使用 Spring Batch,则不应设置自动提交,因为这是您应该信任框架为您处理的事情。下面的部分显示了如何配置的示例:

    5.1.1 配置步骤

    尽管 Step 所需的依赖项列表相对较短, 它是一个极其复杂的类,可能包含许多 合作者。为了简化配置,Spring Batch 可以使用命名空间:

    <job id="sampleJob" job-repository="jobRepository">
        <step id="step1">
            <tasklet transaction-manager="transactionManager">
                <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
            </tasklet>
        </step>
    </job>
    

    上面的配置代表了唯一需要的依赖项 创建一个面向项目的步骤:

    • reader - 提供要处理的项目的 ItemReader。

    • writer - 处理 ItemReader 提供的项目的 ItemWriter。

    • transaction-manager - Spring 的 PlatformTransactionManager,将用于在处理期间开始和提交事务。

    • job-repository - JobRepository 将用于在执行期间定期存储 StepExecution 和 ExecutionContext 处理(就在提交之前)。对于在线(一个 在 a ) 中定义它是元素的一个属性; 对于独立步骤,它被定义为 .

    • commit-interval - 在提交事务之前将处理的项目数。

    【讨论】:

    • 好吧,我已经看到了所有这些,但我仍然无法弄清楚代码中的 Spring 批量提交逻辑。
    • 抱歉,我想我没有完全理解您要解决的问题。您对 Spring Batch 的“穿透黑匣子”以及它如何在内部管理事务的用例是什么?如果我明白这一点,也许我可以提供更多帮助。
    • 我的问题是,当我的 Hikari 数据源自动提交为 false 时,Spring 批处理仍应管理提交,但它没有。所以在我的问题中,我想了解AbstractPlatformTransactionManager.processCommit(DefaultTransactionStatus status) 究竟是如何工作的,以尝试解决我当前的问题。
    • 啊,我明白了。所以 Hikari 和 Spring Batch 彼此纠缠不清,而您正试图解决这个问题。嗯,这有点难。
    • 是的,但似乎我犯了 TransactionManager 配置错误,请检查@Kayaman cmets
    猜你喜欢
    • 2023-03-25
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2019-08-01
    • 2011-06-29
    • 1970-01-01
    相关资源
    最近更新 更多