Java 如何使用Spring集成处理EmptyResultDataAccessException?

Java 如何使用Spring集成处理EmptyResultDataAccessException?,java,spring,spring-integration,Java,Spring,Spring Integration,在处理输入文件之前,我需要检查数据库中是否设置了某些信息。在这种特殊情况下,它是用于处理的客户机名称和参数。如果未设置此信息,文件导入将失败 在许多StackOverflow页面中,用户通过在Java代码中捕获queryForObject生成的EmptyResultDataAccessException异常来解决这些异常的处理问题,queryForObject不返回任何行 问题是Spring Integration在我的代码捕获异常之前就捕获到了异常,理论上,我无法从代码中其他查询可能引发的任何

在处理输入文件之前,我需要检查数据库中是否设置了某些信息。在这种特殊情况下,它是用于处理的客户机名称和参数。如果未设置此信息,文件导入将失败

在许多StackOverflow页面中,用户通过在Java代码中捕获queryForObject生成的EmptyResultDataAccessException异常来解决这些异常的处理问题,queryForObject不返回任何行

问题是Spring Integration在我的代码捕获异常之前就捕获到了异常,理论上,我无法从代码中其他查询可能引发的任何数量的EmptyResultDataAccessException异常中分辨出这个错误

显示try…catch with queryForObject的示例代码段:

    MapSqlParameterSource mapParameters = new MapSqlParameterSource();

    // Step 1 check if client exists at all
    mapParameters.addValue("clientname", clientName);
    try {
        clientID = this.namedParameterJdbcTemplate.queryForObject(FIND_BY_NAME, mapParameters, Long.class);
    } catch (EmptyResultDataAccessException e) {
        SQLException sqle = (SQLException) e.getCause();
        logger.debug("No client was found");
        logger.debug(sqle.getMessage());
        return null;
    }

    return clientID;
在上面的代码中,没有返回任何行,我希望正确地处理它(我还没有对该部分进行编码)。相反,从不触发catch块,而是触发我的通用错误处理程序和关联的错误通道

文件BatchIntegrationConfig.java中的段:

    @Bean
    @ServiceActivator(inputChannel="errorChannel")
    public DefaultErrorHandlingServiceActivator errorLauncher(JobLauncher jobLauncher){
        logger.debug("====> Default Error Handler <====");
        return new DefaultErrorHandlingServiceActivator();
    }
为建议添加了支持Bean和方法:

    @Bean
ExpressionEvaluatingRequestHandlerAdvice handleAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setOnFailureExpression("payload");
    advice.setFailureChannel(customErrorChannel());
    advice.setReturnFailureExpressionResult(true);
    advice.setTrapException(true);
    return advice;
}

private QueueChannel customErrorChannel() {
    return new DirectChannel();
}

我最初在连接此功能时遇到一些问题,但最终,我意识到它正在创建另一个通道,需要对其进行错误监控并进行适当处理。为简单起见,我选择此时不使用另一个频道。

Spring Integration Service Activator可以与
表达式Evaluation RequestHandlerAdvice一起提供,它的工作原理类似于一个
try…catch
,允许您对FailureExpression执行一些逻辑


您的问题可能是捕获(EmptyResultDataAccessException e)
,但这是一个
原因
,而不是
this.namedParameterJdbcTemplate.queryForObject()
调用的根。

虽然可能不是最佳解决方案,但我切换到检查行计数而不是返回实际数据。在这种情况下,可以避免数据异常

上面的主代码移到:

    MapSqlParameterSource mapParameters = new MapSqlParameterSource();
    mapParameters.addValue("clientname", clientName);

    // Step 1 check if client exists at all; if exists, continue
    // Step 2 check if client enrollment rules are available
    if (this.namedParameterJdbcTemplate.queryForObject(COUNT_BY_NAME, mapParameters, Integer.class) == 1) {
        if (this.namedParameterJdbcTemplate.queryForObject(CHECK_RULES_BY_NAME, mapParameters, Integer.class) != 1) return null;
    } else return null;

    return findClientByName(clientName);
然后,我在返回Spring Batch中的调用方法时检查数据:

        if (clientID != null) {
        logger.info("Found client ID ====> " + clientID);
    }
    else {
        throw new ClientSetupJobExecutionException("Client " + 
                fileNameParts[1] + " does not exist or is improperly setup in the database.");
    }

虽然不需要,但我创建了一个自定义Java异常,这在以后的某个时间点可能会很有用。

更新了带有错误堆栈的原始问题,以便可以根据上面最后一段对异常进行审查。OK。检验过的。问题是什么?这就是它的工作原理。
ClientDaoJDBC
抛出
EmptyResultDataAccessException
。它被包装到
MessageHandlingException
,然后包装到
MessageTransformationException
,因为您使用
MemberFileMessageToJobRequest.messageToRequest()
作为
transformer
函数。我指的是@Artem Bilan关于原因与非根本原因之间的问题的评论。我只是想确保它被记录在案。我确实尝试捕获所有3个异常,但Spring Integration仍然首先捕获异常。完全不清楚您在哪里尝试捕获它们。根据堆栈跟踪,没有任何
try…catch
(或者是错误的异常)。这就是它作为
ErrorMessage
发送到
errorChannel
的原因。请重新表述你想要的。任何非
MessaginException
都会被包装到相应的
MessaginException
,因为我们需要
failedMessage
来获取错误的上下文。在最初的文章中,EmptyResultDataAccessException的catch语句位于步骤1和步骤2的注释部分。那是我希望能抓住他们的地方。我更愿意优雅地处理这种情况,而不是走上错误通道。但是,如果我真的必须进入错误通道,我想特别了解异常发生的原因。在我的例子中,客户机没有设置或客户机处理规则没有设置。基本上,我觉得这个问题有多种答案,这取决于贵组织的需要。SpringIntegration提供了处理错误的方法,它们与文档化的设计模式很好地一致。为了验证这个项目的概念,我采用了上述方法并更改了查询。通过这样做,我确切地知道错误发生的时间,并可以相应地作出响应@下面,Artem的解决方案也是有效的。
    MapSqlParameterSource mapParameters = new MapSqlParameterSource();
    mapParameters.addValue("clientname", clientName);

    // Step 1 check if client exists at all; if exists, continue
    // Step 2 check if client enrollment rules are available
    if (this.namedParameterJdbcTemplate.queryForObject(COUNT_BY_NAME, mapParameters, Integer.class) == 1) {
        if (this.namedParameterJdbcTemplate.queryForObject(CHECK_RULES_BY_NAME, mapParameters, Integer.class) != 1) return null;
    } else return null;

    return findClientByName(clientName);
        if (clientID != null) {
        logger.info("Found client ID ====> " + clientID);
    }
    else {
        throw new ClientSetupJobExecutionException("Client " + 
                fileNameParts[1] + " does not exist or is improperly setup in the database.");
    }