mybatis resultmap 字段映射失败主因是列名与属性名未显式匹配,需手动配置且注意大小写、驼峰规则及java bean规范;动态sql须用包裹;#{}用于安全参数,${}仅限白名单校验的元数据拼接;xml需正确声明namespace和dtd/xsd。

MyBatis resultMap 为什么总映射不上字段?
字段为空或 null,不是数据库没查到,大概率是 resultMap 和实体类/SQL 列名对不上。MyBatis 不会自动驼峰转下划线,也不会猜你字段叫 user_name 对应 userName。
- 显式写全
<result column="user_name" property="userName"></result>,别依赖mapUnderscoreToCamelCase=true全局配置——它只对resultType生效,resultMap里必须手动配 - 注意大小写:MySQL 默认不区分列名大小写,但 PostgreSQL 和 Oracle 会严格按双引号里的大小写匹配,
column="USER_NAME"和column="user_name"在某些库中不是一回事 -
property必须是 Java Bean 的可写属性名(即存在setUserName()),不能写成userName_或带下划线的变体
MyBatis XML 中 <if></if> 标签拼 SQL 总报错
常见错误是 <if test="xxx != null"></if> 写在了 <where></where> 外面,或者多个 <if></if> 之间漏了空格,导致生成的 SQL 多出非法逗号或 AND 开头。
- 永远把动态条件包在
<where></where>里:<where><if test="name != null">AND name = #{name}</if></where>,它会自动删掉开头多余的AND或OR -
test表达式里用!= null判断对象,用!"".equals(name)判断字符串是否为空串,别只判name != null就放过空字符串 - 如果要用
<trim prefix="SET" suffixoverrides=","></trim>拼更新语句,确保每个<if></if>内部结尾都带逗号,否则suffixOverrides删不干净
MyBatis #{} 和 ${} 到底该用哪个?
#{} 是预编译占位符,安全;${} 是字符串拼接,快但危险。99% 的场景该用 #{},只有极少数必须拼表名、排序字段时才动 ${}。
- 参数是值(id、name、status)→ 无条件用
#{id},防 SQL 注入 - 参数是列名、表名、
ORDER BY字段 → 只能用${columnName},但必须提前白名单校验,比如if (!ALLOWED_SORT_FIELDS.contains(sortField)) throw new IllegalArgumentException(); -
${}不做类型转换,传入Integer也会原样拼成数字,没有引号;而#{}会根据 JDBC 类型加引号或转义
Mapper.xml 文件找不到或解析失败
不是路径写错就是 DTD 声明或命名空间不对。MyBatis 3.4+ 要求 <mapper></mapper> 必须有 namespace,且值必须和对应 Mapper 接口全限定名一致。
- 检查
<mapper namespace="com.example.UserMapper"></mapper>是否和接口package com.example; public interface UserMapper { ... }完全匹配 - XML 文件名不必和接口同名,但路径要对:Maven 项目里 XML 得放在
src/main/resources/com/example/UserMapper.xml,和接口包路径一致 - 别手写 DTD 引用,用 MyBatis 官方 XSD:
<?xml version="1.0" encoding="UTF-8"?>
最麻烦的是嵌套 resultMap 引用——<association property="dept" resultmap="DeptResultMap"></association> 里 resultMap 值必须带 namespace,比如 com.example.DeptMapper.DeptResultMap,漏了就报 Could not find result map。










