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

MyBatis 一对多与多对一映射详解教程


一、基础概念与场景

  1. 一对多(One-to-Many)
    • 定义:一个父对象包含多个子对象。

例如:一个商品(Goods)对应多个商品详情(GoodsDetail)
• 实体类表现:父类中包含 List<子类> 属性。

// Goods.java
public class Goods {private List<GoodsDetail> goodsDetails; // 一对多关系
}
  1. 多对一(Many-to-One)
    • 定义:多个子对象属于一个父对象。

例如:多个商品详情(GoodsDetail)属于一个商品(Goods)
• 实体类表现:子类中包含父类对象属性。

// GoodsDetail.java
public class GoodsDetail {private Goods goods; // 多对一关系
}

二、XML配置实现

  1. 一对多映射(父→子)
    使用 <collection> 标签,核心配置如下:
<!-- GoodsMapper.xml -->
<resultMap id="rmGoods1" type="Goods"><id column="goods_id" property="goodsId"/><!-- 一对多:通过子查询获取商品详情 --><collection property="goodsDetails" select="goodsDetail.selectByGoodsId" column="goods_id"/>
</resultMap><select id="selectOneToMany" resultMap="rmGoods1">SELECT * FROM t_goods LIMIT 0,10
</select>

• 参数解释:

select:指向子查询的命名空间(如 goodsDetail.selectByGoodsId

column:传递父查询结果中的字段值(如 goods_id)到子查询


  1. 多对一映射(子→父)
    使用 <association> 标签,核心配置如下:
<!-- GoodsDetailMapper.xml -->
<resultMap id="rmGoodsDetail" type="GoodsDetail"><id column="gd_id" property="gdId"/><!-- 多对一:通过父查询获取商品信息 --><association property="goods" select="goods.selectById" column="goods_id"/>
</resultMap><select id="selectManyToOne" resultMap="rmGoodsDetail">SELECT * FROM t_goods_detail LIMIT 0,1
</select>

• 参数解释:

select:指向父查询的命名空间(如 goods.selectById

column:传递当前表的字段值(如 goods_id)到父查询


三、联表查询优化

  1. 一对多联表查询(避免N+1问题)
    直接通过JOIN查询一次性获取父子数据:
<resultMap id="rmGoodsJoin" type="Goods"><collection property="goodsDetails" ofType="GoodsDetail"><id column="gd_id" property="gdId"/><result column="gd_pic_url" property="gdPicUrl"/></collection>
</resultMap><select id="selectJoin" resultMap="rmGoodsJoin">SELECT g.*, d.* FROM t_goods g LEFT JOIN t_goods_detail d ON g.goods_id = d.goods_id
</select>

• 优点:减少数据库查询次数,提升性能


  1. 多对一联表查询
<resultMap id="rmDetailJoin" type="GoodsDetail"><association property="goods" javaType="Goods"><id column="goods_id" property="goodsId"/><result column="title" property="title"/></association>
</resultMap><select id="selectDetailWithGoods" resultMap="rmDetailJoin">SELECT d.*, g.title FROM t_goods_detail d INNER JOIN t_goods g ON d.goods_id = g.goods_id
</select>

四、常见问题与解决方案

  1. N+1查询问题
    • 现象:父查询返回N条数据,触发N次子查询,导致性能低下。

• 解决:

• 开启懒加载:在 mybatis-config.xml 中配置:

```xml
<settings><setting name="lazyLoadingEnabled" value="true"/>
</settings>
```

• 使用联表查询(如上述第三节)


  1. 字段名冲突
    • 现象:联表查询时多个表有相同字段名(如 id)。

• 解决:

• 使用别名区分字段:

```sql
SELECT g.id AS goods_id, d.id AS detail_id
```

• 在 <resultMap> 中明确指定映射关系


五、最佳实践总结

场景推荐方案适用场景
数据量小分步查询(<collection>/<association>字段关联逻辑简单
数据量大联表查询需要一次性获取完整数据
实时性要求高联表查询 + 缓存高频读取场景
更新频繁分步查询 + 懒加载减少无效数据加载

学习建议:

  1. 从简单分步查询入手,理解映射逻辑
  2. 逐步尝试联表查询,对比性能差异
  3. 参考官方文档中的 <resultMap> 高级用法
  4. 通过单元测试验证结果集映射(如 System.out.println(goods.getGoodsDetails().size())
http://www.xdnf.cn/news/4050.html

相关文章:

  • macbook install chromedriver
  • 百度golang开发一面
  • SpringBoot集成CXF框架,实现WebService
  • 2025系统架构师---论面向对象的软件设计
  • Python字符串全面指南:从基础到高级操作
  • 计算机视觉与深度学习 | 点云配准算法综述(1992-2025)
  • Python核心技巧 类与实例:面向对象编程的基石
  • 协程补充---viewModelScope 相关知识点
  • 【计算机视觉】3d人脸重建:3DDFA_V2:实时高精度3D人脸重建与密集对齐技术指南
  • 【NLP】 26. 语言模型原理与概率建模方法详解(Language Models)
  • QT聊天项目DAY08
  • C 语言逻辑运算符:组合判断,构建更复杂的条件
  • Cisco Packet Tracer 选项卡的使用
  • Python中的客户端和服务端交互的基本内容
  • vue实现AI问答Markdown打字机效果
  • 【C/C++】函数模板
  • Auto.js 脚本:清理手机数据但保留账号
  • 第R8周:RNN实现阿尔兹海默病诊断(pytorch)
  • 基于EFISH-SCB-RK3576工控机/SAIL-RK3576核心板的网络安全防火墙技术方案‌(国产化替代J1900的全栈技术解析)
  • Python生活手册-正则表达式:从快递单到咖啡订单的文本魔法
  • Level DB --- MergingIterator
  • Compose 中使用 WebView
  • 基于YOLOv的目标检测训练数据构建方法研究—图像采集、标注、划分与增强一体化流程设计
  • Softmax回归与单层感知机对比
  • 【platform push 提示 Invalid source ref: HEAD】
  • 双目视觉的核心目标
  • NGINX 的 ngx_http_auth_jwt_module模块
  • 模块方法模式(Module Method Pattern)
  • JavaScript 实现输入框的撤销功能
  • 算力经济模型推演:从中心化到去中心化算力市场的转变(区块链+智能合约的算力交易原型设计)