导读:本期聚焦于小伙伴创作的《怎么在MyBatis中实现一对多关联查询_collection标签与嵌套结果映射》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《怎么在MyBatis中实现一对多关联查询_collection标签与嵌套结果映射》有用,将其分享出去将是对创作者最好的鼓励。

在数据库设计中,一对多关系是非常常见的表结构,比如一个用户对应多条订单记录,一个部门对应多个员工。在MyBatis中实现这类一对多关联查询,最常用的方式就是通过collection标签配合嵌套结果映射来完成,这种方式可以直接在一次查询中把主表数据和关联的从表数据一起查询出来,映射到对应的实体类结构中。

怎么在MyBatis中实现一对多关联查询_collection标签与嵌套结果映射

一对多关联查询的实体类定义

首先需要定义主表和从表对应的实体类,主表实体类中需要包含一个从表实体类的集合属性,用来存储关联的从表数据。比如用户和订单的一对多关系,用户实体类如下:

public class User {
    private Integer id;
    private String username;
    private Integer age;
    // 一对多关联属性,存储该用户的所有订单
    private List<Order> orderList;

    // 省略getter、setter和toString方法
}

从表的订单实体类定义如下:

public class Order {
    private Integer id;
    private Integer userId;
    private String orderNo;
    private Double totalAmount;

    // 省略getter、setter和toString方法
}

Mapper接口定义

接下来定义对应的Mapper接口,声明查询方法,这里我们需要查询用户以及对应的所有订单信息:

public interface UserMapper {
    /**
     * 根据id查询用户以及对应的所有订单
     * @param id 用户id
     * @return 包含订单列表的用户对象
     */
    User selectUserWithOrdersById(Integer id);
}

XML映射文件配置

核心的配置在XML映射文件中,需要使用<resultMap>定义嵌套结果映射,通过collection标签配置一对多的关联关系。

嵌套结果映射的配置规则

resultMap中需要先配置主表字段到主表实体类属性的映射,然后使用collection标签配置从表集合属性的映射,collection标签的property属性对应主表实体类中的从表集合属性名,ofType属性对应集合中的元素的类型,也就是从表实体类的全路径或者别名。

完整的XML映射配置示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://ipipp.com/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">

    <!-- 定义一对多关联的resultMap -->
    <resultMap id="UserWithOrdersResultMap" type="com.example.entity.User">
        <!-- 主表User字段映射 -->
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="age" property="age"/>

        <!-- 一对多关联配置,collection标签映射订单集合 -->
        <collection property="orderList" ofType="com.example.entity.Order">
            <id column="order_id" property="id"/>
            <result column="user_id" property="userId"/>
            <result column="order_no" property="orderNo"/>
            <result column="total_amount" property="totalAmount"/>
        </collection>
    </resultMap>

    <!-- 查询用户和对应的所有订单 -->
    <select id="selectUserWithOrdersById" resultMap="UserWithOrdersResultMap">
        SELECT
            u.id AS user_id,
            u.username,
            u.age,
            o.id AS order_id,
            o.user_id,
            o.order_no,
            o.total_amount
        FROM user u
        LEFT JOIN orders o ON u.id = o.user_id
        WHERE u.id = #{id}
    </select>

</mapper>

配置注意事项

  • 主表和从表的字段如果有重名,必须在SQL语句中给字段起不同的别名,否则MyBatis无法正确区分字段对应的映射关系,比如上面的user表和orders表都有id字段,分别起了user_id和order_id的别名。
  • collection标签的ofType属性必须正确填写从表实体类的类型,否则MyBatis无法实例化集合中的元素。
  • 如果使用LEFT JOIN查询,当主表存在但从表没有对应数据时,主表数据会正常返回,从表集合属性会是空集合而不是null。

测试验证

编写测试代码验证查询效果:

public class MyBatisTest {
    public static void main(String[] args) {
        // 获取SqlSession省略,假设已经获取到sqlSession
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectUserWithOrdersById(1);
        System.out.println("用户信息:" + user.getUsername() + ",年龄:" + user.getAge());
        System.out.println("该用户的订单数量:" + user.getOrderList().size());
        for (Order order : user.getOrderList()) {
            System.out.println("订单号:" + order.getOrderNo() + ",总金额:" + order.getTotalAmount());
        }
    }
}

如果数据库中存在id为1的用户,并且有对应的订单记录,运行测试代码就可以看到用户信息和对应的所有订单信息都被正确查询出来,说明一对多关联查询配置生效。

常见问题说明

很多开发者在配置完成后会发现查询结果中主表数据出现重复,比如一个用户有3个订单,查询结果会返回3条用户数据,只是订单不同。这是因为MyBatis的嵌套结果映射默认不会自动去重,如果需要主表数据去重,可以在resultMap的主表id标签中正确配置主键字段,MyBatis会根据主键自动合并相同主表数据的关联集合。另外也可以在SQL语句中使用DISTINCT关键字,但需要注意DISTINCT会对所有查询字段生效,可能会导致结果不符合预期,更推荐使用resultMap的主键配置方式去重。

MyBatis一对多关联查询collection标签嵌套结果映射修改时间:2026-07-19 23:39:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。