Java 如何使用Spring集成处理EmptyResultDataAccessException?
在处理输入文件之前,我需要检查数据库中是否设置了某些信息。在这种特殊情况下,它是用于处理的客户机名称和参数。如果未设置此信息,文件导入将失败 在许多StackOverflow页面中,用户通过在Java代码中捕获queryForObject生成的EmptyResultDataAccessException异常来解决这些异常的处理问题,queryForObject不返回任何行 问题是Spring Integration在我的代码捕获异常之前就捕获到了异常,理论上,我无法从代码中其他查询可能引发的任何数量的EmptyResultDataAccessException异常中分辨出这个错误 显示try…catch with queryForObject的示例代码段:Java 如何使用Spring集成处理EmptyResultDataAccessException?,java,spring,spring-integration,Java,Spring,Spring Integration,在处理输入文件之前,我需要检查数据库中是否设置了某些信息。在这种特殊情况下,它是用于处理的客户机名称和参数。如果未设置此信息,文件导入将失败 在许多StackOverflow页面中,用户通过在Java代码中捕获queryForObject生成的EmptyResultDataAccessException异常来解决这些异常的处理问题,queryForObject不返回任何行 问题是Spring Integration在我的代码捕获异常之前就捕获到了异常,理论上,我无法从代码中其他查询可能引发的任何
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.");
}