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

当ItemWriter中发生异常时,如何防止回滚?

温凯
2023-03-14

我们的编写器设计用于将记录写入关系数据库。如果任何记录发生异常,Spring Batch将对区块中的每条记录执行回滚并重试写入操作。这导致发生SQL重复密钥异常,因为区块中先前处理的记录已成功写入数据库。

我们已经尝试使用noRetry()和noRollback(),明确指定不应该触发重试或回滚的异常列表。

根据Spring Batch在线留档noRollback()可用于防止在ItemWriter上发生错误时回滚:https://docs.spring.io/spring-batch/4.1.x/reference/html/step.html#controllingRollback

然而,这与源代码中的java文档相矛盾,源代码中说FaultTolerantStepBuilder。在写入过程中忽略noRollback():https://docs.spring.io/spring-batch/4.1.x/api/index.html?org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.html

以下是我们的工作定义示例:

    @Bean("my-job")
    public Job job(Step step) {
        return jobBuilderFactory.get("my-job")
                .start(step)
                .build();
    }

    @Bean
    public Step step() {
        return stepBuilderFactory.get("skip-step")
            .<String, String>chunk(3)
            .reader(reader())
            .processor(myprocessor())
            .writer(this::write)
            .faultTolerant()
            .skipLimit(1)
            .skip(JobSkippableException.class)
            .noRollback(JobSkippableException.class)
            .noRetry(JobSkippableException.class)
            .processorNonTransactional()
            .build();
    }

    public ItemReader<String> reader() {
        return new ItemReader<String> () {

            @Override
            public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
                String s = randomUUID().toString(); 
                logger.debug("READ STRING {}", s);  
                return s;
            }
        };
    }

    public void write(List<? extends String> items) {
        for(String s : items) {
            logger.debug("WRITE STRING {}", s);
            throw new JobSkippableException("My skippable exception");
        }
    }

    public ItemProcessor <String, String> myprocessor() {
        return new ItemProcessor<String, String>() {

            @Override
            public String process(String item) throws Exception {
                logger.debug("PROCESS STRING {}", item);
                return item;
            }
        };
    }

我们期望的行为是,写入中发生的异常不会触发重试或回滚。这将防止重复调用数据库,因此不会导致SQL重复密钥异常。

共有1个答案

连德义
2023-03-14

不是一个解决方案,但至少解释了为什么框架不能像您期望的那样运行,我在FaultT的第335-350行中找到:

                    try {
                        doWrite(outputs.getItems());
                    }
                    catch (Exception e) {
                        if (rollbackClassifier.classify(e)) {
                            throw e;
                        }
                        /*
                         * If the exception is marked as no-rollback, we need to
                         * override that, otherwise there's no way to write the
                         * rest of the chunk or to honour the skip listener
                         * contract.
                         */
                        throw new ForceRollbackForWriteSkipException(
                                "Force rollback on skippable exception so that skipped item can be located.", e);                   }
 类似资料:
  • 问题内容: 据我所知,如果在PyQt下的插槽中发生异常,该异常会打印到屏幕上,但不会冒泡。这在我的测试策略中造成了一个问题,因为如果插槽中发生异常,我将不会看到测试失败。 这是一个例子: 请注意,异常永远不会退出程序。 有没有解决此问题的方法? 问题答案: 可以创建一个包装PyQt的新信号/插槽装饰器的装饰器,并为所有插槽提供异常处理。也可以重写QApplication :: notify来捕获未

  • 我在我的骆驼分裂()路线中有一个聚合策略。 splitMessage方法已将数据拆分为3个请求数据。因此,我将点击http目标endpoint3次。 使用聚合策略,我的http响应在前2次被聚合。 第三次http调用因异常而失败。返回给调用者的交换不包含前两个分组交换。 在这种情况下,我如何获得分组交换(成功,异常)。 如果问题不清楚,请告诉我。

  • 问题内容: 我无法避免在RuntimeException之后阻止事务回滚。我的环境是在Websphere 8.0上运行的Spring 4.1 + Hibernate 3.6 + JTA(WebSphereUowTransactionManager)。 首先,一个简单的情况表现出预期的效果。由于我 捕获了RuntimeException ,因此事务提交并成功创建了新资源。 下一个也可以。我声明了 n

  • 假设我有以下代码行, 我的代码为: 现在发生的情况是,当编译器到达}catch(final SQLException se){时,它没有转到它的catch主体,只是脱离了,不知道为什么吗?

  • 问题内容: 我正在使用Hibernate + spring + 批注来处理我的应用程序中的事务。 事务管理器声明如下: 在大多数情况下,此方法效果很好,但是我发现一个问题,我有2种方法,都标有@Transactional: 和 当我调用OuterTestService#outerMethod()时,出现异常 由于只有一个事务(没有嵌套事务),因此整个事务都标记为“仅回滚”。 我发现可以使用noRo

  • 我在做一个基于线性探测的自定义哈希表,在C 11中,我在其中做了一个函数,函数应该返回哈希表中对应键的值,这是我的代码: 问题是,传递的每个键在哈希表中可能没有对应的值。在这个函数中,我无法获得如何处理这个异常。处理这个异常的可能方法是什么?C STL