背景信息
最近在测试环境遇到了这样一个报错,Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: dm.jdbc.driver.DMException: Digital overflow。具体的报错信息大概意思就是说:【org.apache.ibatis.type.TypeException:为参数#1设置非空值时出错,JdbcType为空。尝试为此参数设置不同的JdbcType或不同的配置属性。原因:dm.jdbc.driver.DMException:数字溢出。】 详细的错误信息如下
Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='__frch_item_0.invoiceId', mode=IN, javaType=class java.lang.String, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: dm.jdbc.driver.DMException: Digital overflow
初看到这个错误还是有点疑惑,因为在本地开发时并没有这样的问题,而部署到测试环境就出现了这样的错误提示。
问题分析
由于并不知道具体可能是哪儿引起的错误,我们只能从日志入手,根据日志信息来看,这里可以看到有个 invoiceId javaType=class java.lang.String 而在mybatis 操作数据时又提示了 Error setting non null for parameter #1 with JdbcType null ,最后还提示了dm.jdbc.driver.DMException: Digital overflow 数字溢出。那么这里猜测有没有可能是在插入 invoiceId 数据时发生了数字溢出,可能是字段长度不够用了?
基于上面的分析,又去查看了测试环境的数据库结构,发现测试环境 invoiceId 的数据类型是 Bigint ,而代码在插入数据前拼接参数时传入的 invoiceId 实际时 String 类型,那么这里就会涉及到一个字段类型自动转换的问题。对于数据库来说,当传入的字段类型与表结构的实际字段类型不一致时,数据库自动优化体系会对传入的数据进行一个强制的数据格式转换,那么检查了一下日志信息中的入参 invoiceId 内容为“1104197070038241230170654252239403”,是一段纯数字,强转不会有问题。这是就将原表中的所有数字字段都拿出来做一个测试表 t_sett_pay_apply_invoice_2
CREATE TABLE "CMS_CORE"."t_sett_pay_apply_invoice_2" ( "invoice_id" BIGINT NOT NULL, "amount" DEC(32,8), "tax_rate" DEC(32,8), "tax_amount" DEC(32,8), "not_amount" DEC(32,8), NOT CLUSTER PRIMARY KEY("invoice_id")) STORAGE(ON "CMSTBS", CLUSTERBTR) ;
然后再将日志信息中的插入参数中的数字拿到拼接insert into 语句在 DM管理工具执行插入数据操作,这里看到数据中除了 invoiceId 的长度有点长之外,其他的字段长度都是满足要求的
INSERT INTO "CMS_CORE"."t_sett_pay_apply_invoice_2" VALUES ( '1104197070038241230170654252239403',5000000,9,412844.04,4587155.96);
执行sql语句发现复现了测试环境中日志的报错信息
查阅了文档中关于BIGINT 类型 数据长度,BIGINT
类型的数据长度为8字节。有符号的BIGINT
取值范围是 -9223372036854775808到9223372036854775807。无符号的BIGINT
取值范围是0到18446744073709551615。而我们传入的数据字段 invoiceId 的值转数值类型之后 1104197070038241230170654252239403 很明显已经超过了 BIGINT 类型 数据最大长度,因此才会有 Digital overflow 数字溢出的报错。
问题处理
到这里,关于本次插入数据时提示报错信息 Cause: dm.jdbc.driver.DMException: Digital overflow 的问题就分析清楚了,正是因为表字段 invoiceId 的字段长度不足以保存传入的数据值长度,再次对比了本地数据库字段发现,本地环境数据库 invoiceId 的字段类型是 varchar(64) 类型,而测试环境表结构与本地环境数据库表结构不一致,导致在本地环境可以正常插入数据,而部署到测试环境却报错无法保存数据,更改了测试环境表结构之后,就可以正常插入发票数据了。