核心概念
- ResultMap
MyBatis 的核心映射配置,用于定义数据库字段与 Java 对象属性的对应关系。 - MyBatis-Plus 默认映射
默认开启驼峰转下划线(如userName
→user_name
),字段名一致时无需配置。 - 自定义场景
字段名不一致、嵌套对象(一对一/一对多)、类型转换等复杂映射需自定义 ResultMap。
操作步骤(XML 方式)
1. 创建实体类
@Data
public class User {
private Long id;
private String name; // 数据库字段:real_name
private Integer age; // 数据库字段:user_age
private String email;
// 嵌套对象(部门)
private Department dept; // 数据库字段需联表查询
}
2. 定义 ResultMap
在 UserMapper.xml
中配置:
<resultMap id="UserResultMap" type="User">
<!-- 主键映射 -->
<id column="id" property="id"/>
<!-- 字段名不一致的映射 -->
<result column="real_name" property="name"/>
<result column="user_age" property="age"/>
<!-- 普通字段 -->
<result column="email" property="email"/>
<!-- 嵌套对象映射(一对一) -->
<association property="dept" javaType="Department">
<id column="dept_id" property="id"/>
<result column="dept_name" property="name"/>
</association>
</resultMap>
3. Mapper 接口引用 ResultMap
public interface UserMapper extends BaseMapper<User> {
// 引用自定义 ResultMap
@Select("SELECT u.*, d.id AS dept_id, d.name AS dept_name " +
"FROM user u LEFT JOIN department d ON u.dept_id = d.id " +
"WHERE u.id = #{id}")
@ResultMap("UserResultMap") // 指定 ResultMap ID
User selectUserWithDept(Long id);
}
4. 配置 XML 路径(确保文件被扫描)
# application.yml
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
注解方式实现
@Select("SELECT * FROM user WHERE id = #{id}")
@Results(id = "userMap", value = {
@Result(column = "real_name", property = "name"),
@Result(column = "user_age", property = "age"),
@Result(property = "dept", column = "dept_id",
one = @One(select = "com.example.mapper.DepartmentMapper.selectById"))
})
User selectByIdCustom(Long id);
常见错误与解决方案
字段映射失败(值为 null)
- ✅ 检查字段名拼写(区分大小写)
- ✅ 确认 ResultMap 中
column
与 SQL 查询列名一致 - ✅ 关闭自动驼峰映射(冲突时):
mybatis-plus: configuration: map-underscore-to-camel-case: false
ResultMap 未生效
- ✅ 检查 XML 路径配置是否正确
- ✅ 确认 Mapper 方法引用了正确的
@ResultMap("id")
- ✅ 清理缓存(如开启)并重启项目
嵌套查询 N+1 问题
- ✅ 使用
JOIN
一次性查询(推荐) - ✅ 懒加载:
@One(fetchType = FetchType.LAZY)
- ✅ 使用
注意事项
优先级规则
@ResultMap
> XML ResultMap > 自动驼峰映射 > 字段名严格匹配。关联查询性能
避免多层嵌套select
语句(导致多次查询),优先使用JOIN
+ 单 ResultMap。ID 唯一性
ResultMap 的id
需全局唯一,建议命名规范:类名ResultMap
(如UserResultMap
)。
使用技巧
复用 ResultMap
<!-- 定义基础映射 --> <resultMap id="BaseUserMap" type="User" autoMapping="true"> <id column="id" property="id"/> </resultMap> <!-- 扩展嵌套映射 --> <resultMap id="UserWithDeptMap" extends="BaseUserMap" type="User"> <association property="dept" resultMap="DeptResultMap"/> </resultMap>
自动映射匹配
开启自动映射未配置字段(需确保字段名能匹配):<resultMap id="UserMap" type="User" autoMapping="true"> <id column="id" property="id"/> <!-- 显式配置特殊字段 --> <result column="real_name" property="name"/> </resultMap>
类型处理器
自定义字段类型转换(如枚举、JSON):<result column="tags" property="tags" typeHandler="com.example.handler.JsonTypeHandler"/>
最佳实践与性能优化
精简查询字段
SELECT *
→ 明确指定所需字段,减少数据传输量。避免过度嵌套
超过 3 层的嵌套对象建议拆分为多次查询(通过 Service 层组装)。启用懒加载
对非必要嵌套对象使用懒加载:mybatis-plus: configuration: lazy-loading-enabled: true aggressive-lazy-loading: false # 按需加载
二级缓存慎用
高频更新数据避免缓存,只读数据可开启:<cache eviction="LRU" flushInterval="60000"/>
示例:完整 XML 配置
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="UserResultMap" type="User" autoMapping="false">
<id column="id" property="id"/>
<result column="real_name" property="name"/>
<result column="user_age" property="age"/>
<result column="email" property="email"/>
<association property="dept" javaType="Department">
<id column="dept_id" property="id"/>
<result column="dept_name" property="name"/>
</association>
</resultMap>
<select id="selectUserWithDept" resultMap="UserResultMap">
SELECT
u.id, u.real_name, u.user_age, u.email,
d.id AS dept_id, d.name AS dept_name
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE u.id = #{id}
</select>
</mapper>
关键总结:
- 简单场景:依赖默认映射 +
@TableField
注解。- 复杂映射:XML ResultMap + 显式配置字段/嵌套对象。
- 性能核心:减少查询次数、避免
SELECT *
、合理使用懒加载。