mybatis中使用java包装类传参需规避四大陷阱:一是空值判断仅用!= null,禁用字符串比较;二是禁用${}防npe,动态sql部分须校验非空;三是基本类型与包装类混用时必须@param显式命名;四是数据库布尔字段应配booleantypehandler或改用integer避免映射异常。

Java基本类型的包装类(如 Integer、Long、Boolean 等)在 MyBatis 动态 SQL 中传参时,表面看和普通对象一样用 #{} 即可,但实际存在几个关键陷阱,稍不注意就会导致查询结果为空、SQL 报错或逻辑异常。
空值判断容易误写成字符串比较
包装类变量可能为 null,但在 OGNL 表达式中若错误地写成 status != '' 或 age != "0",会触发隐式类型转换,尤其在 MySQL 等数据库上可能抛出类型不匹配异常。
- ❌ 错误写法:
<if test="status != null and status != ''"></if>(status是Integer,空字符串比较无意义) - ✅ 正确写法:
<if test="status != null"></if>—— 包装类只做null判断即可 - ⚠️ 补充:若业务上需区分“未传”和“传了 0”,应明确约定语义,避免用
0表示“全部”这类模糊逻辑
自动拆箱引发的 NullPointerException
当 XML 中使用 ${} 或在自定义类型处理器中不当调用 intValue() 等方法时,若参数为 null,会直接抛出 NullPointerException,且该异常常发生在 SQL 执行前,堆栈不易定位。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- ❌ 危险场景:
WHERE age > ${age}+ 传入null的Integer→ 字符串拼成WHERE age >,语法错误 - ✅ 安全做法:一律用
#{};动态部分(如排序字段)才考虑${},且必须配合非空校验 - ? 提示:MyBatis 默认对包装类做安全取值,但前提是没绕过预编译机制
与基本类型混用导致参数名冲突
若 Mapper 方法同时接收 int age 和 Integer status,又没加 @Param,MyBatis 会按顺序生成 param1、param2。此时在 <if test="age != null"></if> 中,age 实际是基本类型,永远不为 null,条件恒真,造成逻辑错乱。
- ❌ 模糊接口:
User select(int age, Integer status)→ XML 中test="age != null"始终为 true - ✅ 明确命名:
User select(@Param("age") int age, @Param("status") Integer status),XML 中统一用#{age}和#{status} - ? 关键点:基本类型无法为
null,包装类才能表达“未提供”语义,二者混用必须显式标注
数据库字段类型与 Java 类型不匹配
例如数据库 status TINYINT(1) 对应 Java 的 Boolean 包装类,但 MyBatis 默认不自动转换 TINYINT 和 Boolean。若未配置类型处理器,可能出现 true 写入为 1,但查询时 1 读不到 true。
- ✅ 解决方案:在
mybatis-config.xml中注册BooleanTypeHandler,或在字段级用jdbcType=BIT显式声明 - ✅ 更稳妥:数据库状态字段优先用
tinyint或smallint,Java 层用Integer,避免布尔类型映射歧义
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










