SpringBoot整合Oracle时JSON数字格式字符串无法入库问题排查
异常根因
异常由两个连锁问题共同触发,核心是类型不匹配:
- 首先是Jackson反序列化的自动类型推断问题:你代码中实例化的ObjectMapper没有配置强制类型规则,当JSON字段值为纯数字格式的字符串(如"13"、"15")时,如果CommonCodeDTO类中code字段未明确约束类型、或未加反序列化注解,Jackson会自动将这类值识别为Integer类型;而"X1"这类包含非数字字符的值无法转为数值,会被正常识别为String类型。
- 其次是Oracle对UNION结果集的类型校验规则:MyBatis的foreach拼接多段SELECT通过UNION合并为虚拟表时,要求所有SELECT分支同位置的字段类型完全一致。第一个分支传入的"X1"是VARCHAR2类型,后续分支传入的13、15是NUMBER类型,Oracle解析时直接抛出类型不匹配错误,导致纯数字编码的数据无法入库。
补充:如果你的CommonCodeDTO中code已经定义为String类型,那问题出在MyBatis的自动类型推断——未显式指定jdbcType时,MyBatis会根据传入值的实际类型匹配JDBC类型,部分Oracle驱动版本会对纯数字字符串做特殊类型处理,同样会触发UNION分支类型不一致问题。
修复方案
按以下顺序调整即可解决问题:
- 固定JSON反序列化的类型规则
方法一(全局配置):修改ObjectMapper实例配置,强制文本类型字段就算值为纯数字,也按String类型反序列化:
ObjectMapper obj = new ObjectMapper(); // 对文本类型字段,整数格式输入强制转为字符串 obj.coercionConfigFor(LogicalType.Textual) .setCoercion(CoercionInputShape.Integer, CoercionAction.AsString);
方法二(字段级配置,更稳妥):在CommonCodeDTO类的code字段上加注解,强制按字符串解析:
@JsonFormat(shape = JsonFormat.Shape.STRING) private String code;
- 显式指定MyBatis参数的JDBC类型
将XML中#{item.code}修改为#{item.code, jdbcType=VARCHAR},强制MyBatis按字符串类型传参,从根源上避免JDBC层的类型自动推断,保证UNION所有分支的字段类型统一。 - (可选修复)修正Mapper参数绑定
给Mapper接口的方法参数添加@Param注解,避免MyBatis默认参数解析规则找不到集合参数:
void innoMergeIntoCommonCodeGrade(@Param("commonCodeDTO") CommonCodeDTO[] commonCodeDTO);
- (可选优化)将SQL中拼接用的
UNION改为UNION ALL,你的虚拟表数据本身不存在重复值,UNION ALL不需要做去重排序,执行效率更高,也能减少不必要的类型校验开销。
内容的提问来源于stack exchange,提问作者joskil
相关产品推荐
相关产品推荐

