老师您好,最近在工作中遇到这样一种情况,执行某行代码的时候可能会发生某种异常,通常来说,我可以在catch块中自行解决,然后再把这行代码写一遍来执行,但这样做我认为有两个问题
使用jdbcTemp向数据表中插入数据
jdbcTemplate.update("insert into TABLE_NAME (NAME, SEX, CITY, AGE) values (?,?,?,?)", values.toArray());
当执行上面这行代码的时候,当然,此时可能会发生很多运行时异常,比如表不存在,数据库连不上等等,但在我的项目中,最有可能出现的是“标识符无效”这个异常,意思就是说现在的sql语句中有4个字段要被插入,可是在执行的时候却发现某个字段当前并不存在于数据表中,假设当前目标表只有两个字段,NAME和SEX,那么就会提示“CITY 标识符无效”。
最初,我认为这个问题很好解决,因为可以通过e.getMessage()获得具体是哪个字段还不存在的错误提示,那么只需要在捕获到异常后继续在异常中修改一下表结构,缺啥补啥呗,再执行一下修改表结构的语句加个字段就好了
alter table TABLE_NAME
add CITY varchar(32)
/
表结构修改后再运行一下插入语句就好了。
但是,
当前抛出的错误只能知道一个缺少的字段,再次执行插入语句时,还会提示“AGE标识符无效”,所以实际情况有可能是很多字段都缺少。
现在这个问题被我从另一个层面解决了,就是一旦捕获到标识符异常时,就去select一下表,查询到当前存在的字段,然后把本次插入的字段减掉当前存在的字段,剩下的就是需要add的字段,进行修改表结构,然后再执行一开始的插入语句。
但是,我真正希望的其实是这样的一种机制:
try
{
jdbcTemplate.update(sql语句, values.toArray());
}
catch (DataAccessException e)
{
//捕获到错误
//尝试进行修复
//自动重新执行之前的代码,如果还是报错,则循环这一过程
}
其实思考到这里我也发现了问题所在,这只是一种理想的模型,或者说是一种只适用于当前情况的模型,java目前的异常机制似乎不能直接实现这个过程。
在遇到这个问题之后,总结出来的机制应该会稍稍好一些,那就是多了重试次数(重试次数这个东西只适用于发起网络请求的情况,而不适用上面未知要重试多少次的情况)
使用第三方公司提供的SDK发送请求获得返回,可是对方的服务不稳定,经常性的超时,超时的情况下,调用sdk的方法返回的就是一个null。当我接下来的程序如果拿到一个null,那么我就要重新发起请求,而重试次数则是我写死的,这一过程被我写在了一个for循环中。
private static String getHKSDKResult(String contentType, JSONObject reqBody, Map<String, String> path, int retryNumber, String hkSDKResult)
{
String s = null;
for (int i = 1; i <= retryNumber; i++)
{
s = ArtemisHttpUtil.doPostStringArtemis(path, reqBody.toStringPretty(), null, null, contentType, null);
if (s == null)
{
log.error("SDK请求发生错误,无法正确返回!");
log.error("reqBody:{}\n", reqBody.toStringPretty());
if (retryNumber != 1)
{
log.error("\n进行第{}次重试", i);
}
continue;
}
if (s != null && JSONUtil.isJson(s))
{
hkSDKResult = s;
break;
}
else
{
log.error("海康SDK请求返回了,但不为一个json");
log.error("返回内容:{}", hkSDKResult);
log.error("reqBody:{}", reqBody.toStringPretty());
log.error("\n进行第{}次重试", i);
}
}
return hkSDKResult;
}
这里由于使用了SDK,并没有抛出异常来进行处理,但在我的业务逻辑中,拿到null其实就相当于报错了,我需要重试,我想知道类似的情形,有没有更好更优雅的处理办法呢?