在 MyBatis 中,where id = #{id} 和 where id = #{id,jdbcType=BIGINT} 都是用来设置 SQL 参数的写法,但它们之间有一些细微的区别,主要体现在类型处理和数据库兼容性方面。
✅ 一、基本语法说明
MyBatis 使用 #{xxx} 语法表示这是一个参数占位符,底层会使用 PreparedStatement 设置参数。
1. where id = #{id}
这是最常用的写法,MyBatis 会自动推断参数的 JDBC 类型(jdbcType) ,根据 Java 类型来决定如何设置参数。
例如:
java
深色版本
User user = userMapper.selectById(123L);
如果 id 是 Long 类型,MyBatis 可能会推断为 BIGINT。
2. where id = #{id,jdbcType=BIGINT}
这个写法显式指定了参数的 JDBC 类型为 BIGINT。
sql
深色版本
where id = #{id,jdbcType=BIGINT}
即使 Java 类型是 Long,也明确告诉 MyBatis:这个参数要以 BIGINT 类型来处理。
✅ 二、区别详解
| 特性 | #{id} | #{id,jdbcType=BIGINT} |
|---|---|---|
| 是否显式指定 JDBC 类型 | 否 | 是 |
| MyBatis 如何处理 | 自动推断 | 按指定类型处理 |
| 安全性 | 可能因类型推断错误导致异常 | 更加明确,避免歧义 |
| 兼容性 | 一般没问题,但某些数据库可能出错 | 更兼容,特别是对 NULL 或复杂类型 |
| 推荐场景 | 简单场景,类型明确 | 复杂场景、NULL 值、多数据库兼容 |
✅ 三、为什么要显式指定 jdbcType?
-
当参数可能为 null 时
MyBatis 无法自动推断 null 值的类型,必须显式指定jdbcType,否则会抛出异常:java 深色版本 Caused by: org.apache.ibatis.type.TypeException: Error setting null for parameter #...正确写法:
sql 深色版本 where id = #{id,jdbcType=BIGINT} -
不同数据库对类型敏感
例如 Oracle 和 MySQL 对整型的处理方式不同,显式指定可以避免类型不匹配问题。 -
提升代码可读性和可维护性
显式指定类型可以让其他开发者更清楚地知道字段类型。
✅ 四、常见 jdbcType 对应关系
| Java 类型 | jdbcType 推荐值 |
|---|---|
Long / long | BIGINT |
Integer / int | INTEGER |
String | VARCHAR |
LocalDate | DATE |
LocalDateTime | TIMESTAMP |
BigDecimal | DECIMAL |
Boolean | BIT 或 BOOLEAN |
✅ 五、示例对比
示例 1:自动推断(不推荐用于可为 null 的参数)
sql
深色版本
select * from user where id = #{id}
如果传入的 id 是 null,MyBatis 会抛异常。
示例 2:显式指定类型(推荐)
sql
深色版本
select * from user where id = #{id,jdbcType=BIGINT}
即使 id 为 null,也不会报错,MyBatis 会使用 setNull 方法。
✅ 六、总结
| 写法 | 是否推荐 | 说明 |
|---|---|---|
#{id} | ✅ 适用于简单场景,参数不为 null | 自动推断类型,简洁 |
#{id,jdbcType=BIGINT} | ✅✅ 推荐写法 | 明确类型,兼容性好,适合 null 值或复杂场景 |
如果你使用的是 MyBatis Plus 或者 Spring Boot + MyBatis,建议在 Mapper XML 中统一使用 jdbcType 显式指定类型,特别是在涉及 null 值时,避免不必要的运行时错误。