登录
首页 >  文章 >  java教程

MyBatis一对一关联两种实现方式

时间:2026-03-10 22:00:34 443浏览 收藏

MyBatis中实现一对一(或多对一)关联查询主要有嵌套查询(select属性)和嵌套结果(resultMap + association)两种方式:前者利于SQL复用与逻辑隔离,但易因参数传递不全引发错误,且默认立即加载(eager),设为lazy需确保Session未关闭,否则触发LazyLoadingException;后者性能更优、规避N+1问题,但要求严格对齐字段别名、显式配置映射,且必须定义id子元素以保障对象去重——尤其在复杂嵌套场景下漏掉id会导致重复实例;columnPrefix是解决列名冲突的利器,但仅对嵌套结果生效;还需牢记:MyBatis不区分“一对一”和“多对一”标签,统一用association,关键在业务语义是否保证单条记录,误用于一对多将静默截断为第一条数据。

如何在MyBatis中实现多对一/一对一查询_association标签的两种处理方式

嵌套查询还是嵌套结果?看场景选

直接说结论:嵌套查询(select 属性)适合复用已有 SQL、逻辑隔离强的场景;嵌套结果(resultMap + /)性能更好、N+1 问题更少,但要手动对齐字段别名。

常见错误现象是用了 select 却没写全参数传递,或嵌套结果里漏了 导致关联对象重复创建(尤其一对多嵌套在多对一里时)。

  • 嵌套查询:,注意 column 必须能被外层 SQL 的结果集提供,且 selectUserById 的参数类型要匹配(如单个 int 或封装了 user_id 的对象)
  • 嵌套结果:,字段别名必须和 column 一致(比如 SQL 里得写 u.id as user_id, u.name as user_name
  • 嵌套结果不支持自动映射(autoMapping 默认关闭),哪怕开了,也只映射同名字段,user_namename 这种仍需显式写

fetchType 怎么影响实际执行

默认是 fetchType="eager",只要查主表就立刻触发关联查询;设成 lazy 后,只有首次访问该属性时才查(前提是开启了懒加载,且 session 未关闭)。

容易踩的坑是:设了 lazy 却在 service 层就返回了对象,controller 里再取 user.name 就报 LazyLoadingException —— 因为 session 已关闭。

  • 懒加载生效前提:全局配置 lazyLoadingEnabled=true,且 aggressiveLazyLoading=false(新版 MyBatis 默认如此)
  • fetchType 是局部开关,优先级高于全局 eager 配置
  • 嵌套查询方式下,fetchType="lazy" 会生成代理对象;嵌套结果方式下,fetchType 无效(因为没额外 SQL 可延迟)

多对一和一对一在 上没区别,但别混淆

MyBatis 不区分“多对一”和“一对一”,都用 ;真正区分的是数据量:只要目标记录最多一条,就用它。反过来,如果误把一对多写成 ,只会取第一条,还不会报错。

典型错误是看到“用户有多个订单”,就想当然在 UserMapper.xml 里用 ,结果永远只拿到一个 Order 对象。

  • 一对一/多对一:用
  • 一对多/多对多:必须用
  • javaTypeofType 别写反——前者是单个对象类型,后者是集合元素类型

列名冲突时,columnPrefix 怎么用

当主表和关联表都有 idname 字段,又不想靠别名硬凑,columnPrefix 是最干净的解法。

它不是给 SQL 加前缀,而是告诉 MyBatis:“所有 里的 column 值,都自动加这个前缀再去找结果集字段”。所以 SQL 里必须提前用别名预留好位置。

  • SQL 写法:SELECT o.id, o.title, u.id as user_id, u.name as user_name FROM order o LEFT JOIN user u ON o.user_id = u.id
  • XML 写法:
  • columnPrefix 对嵌套查询方式无效,只作用于嵌套结果
  • 别写成 columnPrefix="user."columnPrefix="user." —— 点号或下划线必须和 SQL 别名严格一致

最常被忽略的是嵌套结果中 的必要性:它不只是为了主键映射,更是 MyBatis 关联对象去重的依据。漏掉它,一对多嵌套在多对一里时,可能创建多个重复的关联对象实例。

本篇关于《MyBatis一对一关联两种实现方式》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>