MyBatis 中 ResultMap 的高级用法指南

举报
bug菌 发表于 2024/12/31 09:55:51 2024/12/31
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!欢迎点赞&&收藏&&订阅。@TOC 📝 前言:为何使用 ResultMap?在 MyBatis 中,ResultMap 是用于映射查询结果与 Java 对象之间关系的工具。虽然 MyBatis 支持 resultType 的简单映射方式,但当涉及到复杂映射需求(如字段名不匹配、嵌套对象、多...

🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!欢迎点赞&&收藏&&订阅。

@TOC

📝 前言:为何使用 ResultMap?

在 MyBatis 中,ResultMap 是用于映射查询结果与 Java 对象之间关系的工具。虽然 MyBatis 支持 resultType 的简单映射方式,但当涉及到复杂映射需求(如字段名不匹配、嵌套对象、多表查询)时,ResultMap 提供了更灵活、更强大的解决方案。

本指南将深入探讨 ResultMap 的高级用法,包括别名映射、嵌套结果映射、多表联合查询映射等。


📖 目录

  1. 🧩 基础回顾:ResultMap 的基本使用
  2. 🔄 字段名与属性名不一致的映射
  3. 🌐 嵌套结果映射:一对一映射
  4. 📚 嵌套集合映射:一对多映射
  5. ⚙️ 多表联合查询映射
  6. 高级技巧:动态结果映射与继承

🧩 基础回顾:ResultMap 的基本使用

ResultMap 是在 MyBatis 配置文件中定义的,用于描述 SQL 查询结果如何映射到 Java 对象。

示例:基础 ResultMap

数据库表结构:

假设我们有一张 user 表:

CREATE TABLE user (
    id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

对应的 Java 类:

public class User {
    private Integer id;
    private String username;
    private String email;

    // Getter 和 Setter 略
}

ResultMap 定义:

在 MyBatis 的 XML 映射文件中,定义如下:

<resultMap id="UserResultMap" type="com.example.User">
    <id column="id" property="id" />
    <result column="username" property="username" />
    <result column="email" property="email" />
</resultMap>

SQL 查询:

<select id="getUserById" resultMap="UserResultMap">
    SELECT id, username, email FROM user WHERE id = #{id}
</select>

🔄 字段名与属性名不一致的映射

在实际项目中,数据库字段名可能与 Java 属性名不一致,此时需要使用 ResultMap 显式指定映射关系。

场景:字段名不一致

数据库表:

CREATE TABLE user (
    id INT PRIMARY KEY,
    user_name VARCHAR(50), -- 注意:字段名是 user_name
    user_email VARCHAR(100) -- 注意:字段名是 user_email
);

对应的 Java 类:

public class User {
    private Integer id;
    private String username; // Java 属性名为 username
    private String email;    // Java 属性名为 email

    // Getter 和 Setter 略
}

ResultMap 映射:

<resultMap id="UserResultMap" type="com.example.User">
    <id column="id" property="id" />
    <result column="user_name" property="username" />
    <result column="user_email" property="email" />
</resultMap>

🌐 嵌套结果映射:一对一映射

ResultMap 支持将查询结果嵌套映射到关联对象(如外键关联)。

场景:用户关联地址信息

数据库表:

CREATE TABLE user (
    id INT PRIMARY KEY,
    username VARCHAR(50),
    address_id INT
);

CREATE TABLE address (
    id INT PRIMARY KEY,
    street VARCHAR(100),
    city VARCHAR(50)
);

Java 类:

public class Address {
    private Integer id;
    private String street;
    private String city;

    // Getter 和 Setter 略
}

public class User {
    private Integer id;
    private String username;
    private Address address; // 嵌套对象

    // Getter 和 Setter 略
}

ResultMap 映射:

<resultMap id="AddressResultMap" type="com.example.Address">
    <id column="id" property="id" />
    <result column="street" property="street" />
    <result column="city" property="city" />
</resultMap>

<resultMap id="UserResultMap" type="com.example.User">
    <id column="id" property="id" />
    <result column="username" property="username" />
    <association property="address" javaType="com.example.Address" resultMap="AddressResultMap" />
</resultMap>

SQL 查询:

<select id="getUserWithAddress" resultMap="UserResultMap">
    SELECT u.id, u.username, a.id AS address_id, a.street, a.city
    FROM user u
    LEFT JOIN address a ON u.address_id = a.id
    WHERE u.id = #{id}
</select>

📚 嵌套集合映射:一对多映射

ResultMap 支持将查询结果映射到嵌套的集合(如一对多关系)。

场景:用户与订单

数据库表:

CREATE TABLE user (
    id INT PRIMARY KEY,
    username VARCHAR(50)
);

CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT,
    order_name VARCHAR(100)
);

Java 类:

public class Order {
    private Integer id;
    private String orderName;

    // Getter 和 Setter 略
}

public class User {
    private Integer id;
    private String username;
    private List<Order> orders; // 嵌套集合

    // Getter 和 Setter 略
}

ResultMap 映射:

<resultMap id="OrderResultMap" type="com.example.Order">
    <id column="id" property="id" />
    <result column="order_name" property="orderName" />
</resultMap>

<resultMap id="UserResultMap" type="com.example.User">
    <id column="id" property="id" />
    <result column="username" property="username" />
    <collection property="orders" ofType="com.example.Order" resultMap="OrderResultMap" />
</resultMap>

SQL 查询:

<select id="getUserWithOrders" resultMap="UserResultMap">
    SELECT u.id AS user_id, u.username, o.id AS order_id, o.order_name
    FROM user u
    LEFT JOIN orders o ON u.id = o.user_id
</select>

⚙️ 多表联合查询映射

在复杂的多表联合查询中,可以通过 ResultMap 将多张表的数据映射到多个对象中。

场景:用户关联角色与权限

数据库表:

CREATE TABLE user (
    id INT PRIMARY KEY,
    username VARCHAR(50)
);

CREATE TABLE role (
    id INT PRIMARY KEY,
    role_name VARCHAR(50)
);

CREATE TABLE permission (
    id INT PRIMARY KEY,
    permission_name VARCHAR(50)
);

CREATE TABLE user_role (
    user_id INT,
    role_id INT
);

CREATE TABLE role_permission (
    role_id INT,
    permission_id INT
);

Java 类:

public class Permission {
    private Integer id;
    private String permissionName;

    // Getter 和 Setter 略
}

public class Role {
    private Integer id;
    private String roleName;
    private List<Permission> permissions;

    // Getter 和 Setter 略
}

public class User {
    private Integer id;
    private String username;
    private List<Role> roles;

    // Getter 和 Setter 略
}

ResultMap 映射:

<resultMap id="PermissionResultMap" type="com.example.Permission">
    <id column="id" property="id" />
    <result column="permission_name" property="permissionName" />
</resultMap>

<resultMap id="RoleResultMap" type="com.example.Role">
    <id column="id" property="id" />
    <result column="role_name" property="roleName" />
    <collection property="permissions" ofType="com.example.Permission" resultMap="PermissionResultMap" />
</resultMap>

<resultMap id="UserResultMap" type="com.example.User">
    <id column="id" property="id" />
    <result column="username" property="username" />
    <collection property="roles" ofType="com.example.Role" resultMap="RoleResultMap" />
</resultMap>

SQL 查询:

<select id="getUserWithRolesAndPermissions" resultMap="UserResultMap">
    SELECT 
        u.id AS user_id, u.username, 
        r.id AS role_id, r.role_name,
        p.id AS permission_id, p.permission_name
    FROM user u
    LEFT JOIN user_role ur ON u.id = ur.user_id
    LEFT JOIN role r ON ur.role_id = r.id
    LEFT JOIN role_permission rp ON r.id = rp.role_id
    LEFT JOIN permission p ON rp.permission_id = p.id
</select>

高级技巧:动态结果映射与继承

1️⃣ 动态结果映射

使用动态 SQL(如 <if><choose>)控制字段映射的动态性。

2️⃣ ResultMap 继承

通过 extends 关键字继承已有的 ResultMap,避免重复定义。


💡 总结与最佳实践

  1. 使用 ResultMap 时,优先考虑字段的映射一致性,减少额外的配置工作。
  2. 对于复杂的嵌套对象和多表查询,分层定义 ResultMap,提高代码的可读性和复用性。
  3. 利用动态 SQL 和 ResultMap 继承,处理动态需求和减少冗余配置。

通过灵活运用 MyBatis 的 ResultMap,你可以轻松实现复杂的对象映射需求,从而让数据与业务模型无缝对接!🚀✨

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。