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

块中的Spring批处理异常

谭云瀚
2023-03-14

步骤1:从数据库中加载10条记录。(Tasklet负责该工作)

步骤2:使用提交间隔=1的ItemReader、ItemProcessor、ItemWriter实现配置了面向块的处理

据我所知,对于每一个记录

>

  • 我的问题是假设它处理了六条记录,而现在在ItemProcessor实现中的第7条记录出现了异常,它尝试回滚,但由于事务处于未知状态而无法回滚

    即使它不能回滚第7条记录的tx,它也不会处理第8、9、10条记录,作业也会停止。

    注意:ItemProcessor实现正在调用使用@transactional(ReadOnly=False)注释标记为事务性的服务(@Service annotated)。

    请提出解决方案。

    下面的ItemProcessor代码

    public Long process(LoanApplication loanApplication)throws Exception {
        Long createLoan = null;
        LoanStatus loanStatus = null;
        StaffUser user = staffUserService.getStaffUserByName(Constants.AUTO_USER);
        String notes = null;
        try{
            try{
    
                loanValidationService.validate(loanApplication);
    
                loanStatus=LoanStatus.U;
    
            }catch(LoanValidationException e){
                loanStatus=LoanStatus.UC;
                notes=e.getMessage();
            }
    
            dataLoadLoanManagementService.setText(notes);
            createLoan = dataLoadLoanManagementService.createLoan(loanApplication, user,loanStatus);
        }catch(Exception le){
            logger.error("Error creating the loan application ;  Parent Application Ref : " 
                + loanApplication
                + " with status as " +(loanStatus!=null ?loanStatus.getStatus():loanStatus)
                +"\n"
                +" School Ref :"
                + loanApplication.getSchoolRef()
                +"\n"
                +" Client Details :"
                +loanApplication.getClientDetails()
                + "Error Details: " + ExceptionUtils.getStackTrace(le));
    
    
        }   
        return createLoan;
    }
    

    即使配置了可跳过的异常类,这也不起作用。
    为了更好地解释,我在项目处理器中得到了持久性异常,并捕获了它,因此Spring批处理执行了writer,但在writer执行之后,我得到了下面的异常

    INFO  06-21 11:38:00 Commit failed while step execution data was already updated. Reverting to old version.  (TaskletStep.java:342) 
    ERROR 06-21 11:38:00 Rolling back with transaction in unknown state  (TaskletStep.java:351) 
    ERROR 06-21 11:38:00 Encountered an error executing the step  (AbstractStep.java:212)
    org.springframework.transaction.TransactionSystemException: Could not commit JPA   transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    
  • 共有1个答案

    严阳秋
    2023-03-14

    对于您的两个问题,跳过prosessor阶段发生的异常将解决您的问题。

    如果您知道异常的根本原因,这可以通过skippable-exception-classes元素来配置。例如,如果您在处理器阶段遇到一个被零除的异常,并且希望忽略它,那么示例配置可能是:

    <chunk reader="reader" processor="processor" writer="writer" 
    commit-interval="1" >
    <skippable-exception-classes>
    <include class="java.lang.ArithmeticException" />
    </skippable-exception-classes>
    </chunk>
    

    由于给定的异常类及其子类将被跳过,您甚至可以尝试java.lang.exception

     类似资料:
    • 我对Spring批处理跳过逻辑有一些问题。我已经配置了一个作业的步骤来跳过两个异常(SQLIntegrityConstraintViolation异常和乐观锁定失败异常): 但当作业运行时,由于我将其配置为跳过的异常,作业以未知状态完成: 我做错什么了吗?我希望这一步跳过负责抛出其中一个异常的项,并继续处理,以便以完成状态结束。

    • 我在表中总共有8条记录,其中6条在spring批处理调用read时可以使用jpareader。现在我将页面大小和块大小设置为1以进行测试。期望作业运行时,它应该进行6次读取调用,然后它应该逐个处理,逐个写入。但实际上发生的是,它只是调用read 4次(从日志中我可以看到这样读取页面0...1)并处理4个,其中一个由于不匹配写入标准而被过滤掉,然后它只是更新了3个记录,作业标记为成功完成。

    • 我有下一个spring批处理配置类: 启动应用程序时,我收到下一个异常:

    • 如果我正在读写本地文件,那么对远程数据库服务器的更新相对昂贵。如果增加[chunk-size],内存使用量就会上升。 提交频率对编写本地文件并没有太大的影响,所以对我来说,元数据更新才是一个问题。该步骤是可重新启动的,因此从技术上讲,我不需要记录中间提交计数。 对于JobRepository,我可以只使用map或内存数据库,但我需要其他信息,例如持久化的开始/结束时间,而且这个问题只涉及一个步骤。

    • 我正在学习spring batch,并试图理解在异常期间项目处理器是如何工作的。 我试图通过在我的项目处理器中为一条记录手动抛出异常来模拟异常 现在根据跳过限制,当异常被抛出时,项目处理器将重新处理块并跳过抛出错误的项目,项目写入也将所有记录插入数据库,除了一条异常记录。 这一切都很好,因为我的处理器,它只是转换为大写字母名称,它可以运行很多次,但影响很大。 其他的选择是什么?

    • 我正在尝试实现一个Spring批处理作业,为了处理记录,它需要2-3个db调用,这会减慢记录的处理速度(大小为100万)。如果我使用基于块的处理,它会单独处理每条记录,性能会很慢。因此,我需要一次性处理1000条记录,作为批量处理,这将减少数据库调用,并提高性能。但我的问题是,如果我实现Tasklet,那么我也会失去可重启性和重试/跳过功能,如果使用AggregateInputReader实现,我