必须在数据进入业务逻辑前将字符串转为数字,如用强类型dto、mybatis typehandler或jdbc getxxx方法,并在关键计算中使用bigdecimal字符串构造器。

后端传来的数字常以字符串形式存在,比如 "1000" 和 "2000",若直接用 + 运算,结果是 "10002000" 而非 3000。问题核心不在前端展示,而在数据层未做类型校验与强制转型——必须在数据进入业务逻辑前,就把它转成真正的数字。
明确数据来源并拦截原始字符串
多数加法错误源于接口接收参数未做类型约束。例如 Spring Boot 的 Controller 接收 JSON 字段:
- 错误写法:
@RequestBody Map<string object> data</string>→ value 可能是"123"字符串,后续直接相加就出错 - 推荐做法:用强类型 DTO,字段声明为
Integer或BigDecimal,配合@Valid校验;Jackson 默认会尝试将合法数字字符串转为数值类型 - 若必须用
Object或String接收(如动态字段),应在 Service 层或 DAO 入口处统一清洗,不等到计算时才处理
在数据访问层做安全转型(DAO/Repository 层)
数据库查询结果、MyBatis 返回值、JDBC ResultSet 取值等环节,最容易隐式保留字符串。需主动干预:
- MyBatis 中避免
<result column="amount" property="amount"></result>直接映射到String字段;应映射到Integer、Long或BigDecimal - 若数据库字段是
VARCHAR存数字(如兼容旧系统),可在 MyBatis 的resultMap中用typeHandler自定义转换逻辑,例如对含逗号、空格、单位的字符串先清洗再转数字 - JDBC 原生调用时,不用
rs.getString("num")后再手动Integer.parseInt();优先用rs.getInt("num")或rs.getBigDecimal("num"),驱动会自动按 JDBC 类型转换,失败则抛异常,便于早暴露问题
使用工具类封装可信赖的转型逻辑
避免零散使用 Integer.parseInt()(易抛 NumberFormatException),应封装健壮方法:
- 对可能含空格、符号、千分位的字符串,先正则清洗:
str.replaceAll("[^\d.-]", ""),再判断是否为空或仅含小数点 - 推荐用
NumberUtils.createInteger(str)(Apache Commons Lang)或BigDecimalUtils.parse(str)(自定义),它们返回null而非抛异常,便于空值处理 - 关键计算场景(如金额累加)强制使用
BigDecimal,构造时用字符串构造器:new BigDecimal("1000.50"),避免double精度污染
SQL 层预防:在查询阶段完成类型归一
当加法逻辑下推到数据库(如 SUM、CASE WHEN 计算),字符串字段参与运算会报错或静默拼接:
- PostgreSQL:用
NULLIF(col, '')::NUMERIC或TO_NUMBER(col, '999999999')强制转数字,配合正则过滤非数字:col ~ '^[+-]?[0-9]*.?[0-9]+$' - MySQL:用
CAST(col AS DECIMAL)或CONVERT(col, DECIMAL),但需提前TRIM()和REPLACE(col, ',', '') - MyBatis XML 中避免
#{param} + #{otherParam}拼在 SQL 里相加——若两者是字符串,数据库仍可能当作字符串拼接;应确保传入参数已是数字类型,或在 SQL 中显式转换











