当前位置: 首页 > news >正文

MyBatis的级联查询(一对一、一对多、多对多)

MyBatis的级联查询

级联的优点是获取关联数据十分便捷。但是级联过多会增加系统的复杂度,同时降低系统的性能,此增彼减。所以记录超过 3 层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合、负载和难以维护。
标签说明:

  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)。
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
    MyBatis的级联查询(一对一、一对多、多对多)主要通过ResultMap<association><collection>标签实现。

1.一对一关系

场景:如订单(Order)与用户(User)、身份证与公民,一个订单仅对应一个用户。

1. 建表原则

  • 主键对应:两表主键一致,直接通过主键关联。
  • 外键唯一约束:在任意一方添加外键并设置唯一约束(如user_id字段)

2. 实现方式

  • 分步查询:分两次查询,先查主表,再通过外键查询关联表。

    <resultMap id="OrderResult" type="Order">
      <id property="id" column="id"/>
      <association property="user" column="user_id" select="findUserById"/>
    </resultMap>
    

    需定义findUserById的查询语句

  • 嵌套结果映射:单次联表查询,通过<association>映射关联对象。

    <resultMap id="OrderWithUserResult" type="Order">
      <id property="id" column="id"/>
      <association property="user" javaType="User">
        <id property="id" column="user_id"/>
        <result property="username" column="username"/>
      </association>
    </resultMap>
    

    SQL需使用JOIN联表查询


2.一对多关系

场景:如班级(Clazz)与学生(Student),一个班级对应多个学生。

1. 建表原则

  • 在多的一方(学生表)添加外键指向一的一方(班级表主键)

2. 实现方式

  • 嵌套查询:分两次查询,先查主表,再通过外键查关联表集合。

    <resultMap id="ClazzResult" type="Clazz">
      <collection property="students" column="id" select="findStudentsByClazzId"/>
    </resultMap>
    
  • 嵌套结果映射:单次联表查询,通过<collection>映射集合。

    <resultMap id="ClazzWithStudentsResult" type="Clazz">
      <id property="id" column="id"/>
      <collection property="students" ofType="Student">
        <id property="id" column="student_id"/>
        <result property="name" column="student_name"/>
      </collection>
    </resultMap>
    

    SQL需使用LEFT JOIN并关联外键

3.多对多关系

场景:如用户(User)与角色(Role),一个用户可拥有多个角色,一个角色可分配给多个用户。

1. 建表原则

  • 通过中间表关联两表主键(如user_role表)

2. 实现方式

  • 嵌套结果映射:通过两次JOIN联表查询,将中间表与主表关联。

    <resultMap id="RoleWithUsersResult" type="Role">
      <id property="roleId" column="rid"/>
      <collection property="users" ofType="User">
        <id property="id" column="user_id"/>
        <result property="username" column="username"/>
      </collection>
    </resultMap>
    

    SQL示例:

    SQLSELECT r.*, u.* FROM role r 
    LEFT JOIN user_role ur ON r.id = ur.rid 
    LEFT JOIN user u ON ur.uid = u.id
    

4.核心配置标签对比

关系类型标签用途关联对象类型
一对一<association>映射单个关联对象javaType
一对多<collection>映射对象集合ofType
多对多<collection>通过中间表映射双向一对多关系ofType + 联表查询

5.优化建议

  1. 延迟加载:在嵌套查询中启用lazyLoadingEnabled,避免一次性加载所有关联数据。
  2. 动态SQL:通过<if><foreach>等标签处理复杂条件
  3. 联表查询 vs 嵌套查询:联表查询减少数据库交互次数,但可能返回冗余数据;嵌套查询更灵活但可能引发N+1问题

6.一对多和多对一的使用异同总结

特性一对多多对一
数据库关系主表(一)的一条记录对应从表(多)的多条记录从表(多)的外键指向主表(一)的主键
映射配置在“一”端使用 <collection> 标签映射集合属性在“多”端使用 <many-to-one> 标签映射单对象属性
外键位置外键位于“多”的表,指向“一”的主键与一对多相同,但视角相反(从“多”向“一”看)
查询方向通常从“一”端查询关联的“多”端数据(如班级查询学生)通常从“多”端查询关联的“一”端数据(如学生查询班级)
数据维护插入数据时需先维护“一”端,删除时需先删除“多”端操作顺序与一对多一致,但逻辑上从“多”端操作
应用场景适合主表与从表的层级关系(如部门与员工)适合从表需要频繁引用主表的场景(如订单与客户)

关键区别

  • 视角差异:一对多是从“一”端指向“多”端,而多对一是从“多”端指向“一”端,本质是同一关系的双向表达
  • 映射标签:在ORM框架(如Hibernate)中,一对多使用<collection>多对一使用<many-to-one>
  • 数据操作逻辑:一对多的查询可能涉及集合遍历(如班级所有学生),而多对一更关注单对象关联(如学生所属班级)

7.使用多对多时的核心要点

  1. 中间表设计

    • 必须通过中间表(如Student_Courses)维护多对多关系,存储两表主键作为外键
    • 若需记录额外属性(如选课时间),需扩展中间表为独立实体(如Enrollment)
  2. 查询优化

    • 使用JOIN连接三张表,避免多次单表查询导致的性能问题
    • 分页处理大数据量时,优先在中间表或主表过滤以减少笛卡尔积爆炸
  3. 结果映射

    • 在ORM框架中通过<collection>标签嵌套映射关联数据,如学生对象包含课程集合
    • 双向关联时需避免循环引用(如学生引用课程,课程又引用学生),可通过DTO解耦或注解忽略
  4. 数据一致性

    • 插入时需先操作主表(学生、课程),再操作中间表;删除时需先解除中间表关联

    • 使用事务保证关联操作的原子性,避免部分失败导致脏数据

  5. 性能与冗余

    • 添加索引优化中间表的外键字段,加速查询
    • 避免在中间表中存储非关联数据,保持表的轻量化

相关文章:

  • 前端系统测试(单元、集成、数据|性能|回归)
  • Spring Boot中的404错误:原因、影响及处理策略
  • 基于阿里云服务器搭建个人图床
  • 如何使用Cursor的claude-3.7模型来开发高保真的原型设计图,学会写好的提示词人人都是设计师
  • MySQL 存储引擎与事务深度解析
  • opencv+ONNX模型的推理
  • 不定方程求解(信息学奥赛一本通-1101)
  • EB-Cable许可管理中的数据安全与隐私保护
  • 江科大51单片机笔记【16】AD/DA(上)
  • Linux 跨进程同步方案
  • MySQL与Canal、RabbitMQ集成指南
  • 分布式存储学习——HBase表结构设计
  • 修改trae全局默认的JDK版本
  • Windows软件插件-音视频文件读取器
  • python数据分析--pandas读取数据--按行和列提取数据
  • 50个经典的python库
  • Python函数的递归调用
  • Flutter_学习记录_video_player、chewie 播放视频
  • Github 2025-03-12 C开源项目日报Top5
  • [洛谷]P1123 取数游戏
  • 王受文已任中华全国工商业联合会领导班子成员
  • 五大国货美妆去年业绩分化:珀莱雅百亿营收领跑,上海家化转亏
  • 海尔智家一季度营收791亿元:净利润增长15%,海外市场收入增超12%
  • 人民日报:在大有可为的时代大有作为
  • 临港迎来鸿蒙智行“尚界”整车及电池配套项目,首款车型今秋上市
  • 10台核电新机组获核准,上海核电厂商独揽超500亿元订单