写入只读列触发UncategorizedSQLException时能否进行异常恢复?
方案结论
你完全可以移除查询中的只读列相关部分后重新构造语句执行,这是该场景下非常合理的异常恢复逻辑,实现时注意以下细节即可:
- 不要硬编码固定的只读列名,从异常信息中动态提取触发报错的列名,适配所有动态出现的只读列场景
- 提取到只读列名后优先更新本地存储的只读列列表,从根源降低后续同类异常的触发概率
- 调整参数时要同步修改PreparedStatement的参数顺序,避免出现参数数量、位置不匹配的新报错
- 增加重试次数上限,避免一条SQL存在多个只读列时进入无限重试循环
代码实现示例
你可以参考以下逻辑补全catch块的恢复代码:
} catch (UncategorizedSQLException e) { String cause = e.getMessage(); if (cause.contains("This column is read-only")) { // 1. 正则提取只读列名 Pattern pattern = Pattern.compile("Column \\[(.*?)\\] could not be updated"); Matcher matcher = pattern.matcher(cause); String readOnlyColumn = null; if (matcher.find()) { readOnlyColumn = matcher.group(1); // 2. 更新本地只读列缓存 localReadOnlyColumns.add(readOnlyColumn); } if (readOnlyColumn == null) { throw e; // 列名提取失败直接抛出原异常 } // 3. 移除待更新字段列表和参数列表中对应的只读列项 int columnIndex = updateColumns.indexOf(readOnlyColumn); if (columnIndex != -1) { updateColumns.remove(columnIndex); params.remove(columnIndex); } // 4. 重新生成UPDATE语句执行 String newUpdateSql = generateUpdateSql(updateColumns); // 自行实现的SQL拼接方法,保持原转义规则 jdbcTemplate.update(newUpdateSql, params.toArray()); } }
边界情况说明
- 该方案仅在更新场景下通用,如果是插入操作触发该异常,需要先确认该只读列是否支持缺省:如果是数据库自动生成的列(如自增ID、默认值生成的创建时间),移除后可正常插入;如果是无默认值的必填只读列,无法恢复,直接终止操作抛出异常即可
- 动态拼接SQL时注意保持列名的转义规则,避免列名中的空格、特殊字符触发SQL语法错误
内容的提问来源于stack exchange,提问作者Keshavram Kuduwa
相关产品推荐
相关产品推荐

