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

MyBatis-Flex多表关联查询指南

MyBatis-Flex 提供了强大且灵活的多表关联查询支持,其核心是通过 QueryWrapperRelations 注解来实现的。与 MyBatis-Plus 等框架的关联查询不同,MyBatis-Flex 的关联查询是在不涉及 JOIN 的 SQL 的情况下,通过多次查询来实现的,这种方式在某些场景下(如分页、大数据量)反而有更好的性能表现。

MyBatis-Flex 的多表关联主要分为两种类型:

  1. 基于 QueryWrapper 的关联查询(动态、手动)
  2. 基于 @Relation 注解的关联查询(静态、自动)

1. 基于 QueryWrapper 的关联查询 (Manual)

这种方式非常灵活,你可以通过 QueryWrapper 动态地指定关联关系和查询条件。它主要通过 select(...)leftJoin/innerJoin 等方法来实现,但其底层机制依然是分开查询再组合。

核心语法示例:

假设我们有 Account(账户)表和 Book(书籍)表,一个账户对应多本书。

// 1. 查询账户及其书籍(1对多)
QueryWrapper query = QueryWrapper.create().select() // 查询主表(Account)的所有字段.from(Account.class)// 使用 leftJoin 或 innerJoin 定义关联关系(注意:这只是定义关系,不生成SQL JOIN).leftJoin(Book.class).on(Account::getId).eq(Book::getAccountId))// 添加查询条件.where(Account::getUserName).like("张三").and(Book::getPublishDate).ge(LocalDate.now().minusYears(1));// 执行查询
// 注意:这里返回的仍然是 List<Account>,但MyBatis-Flex会通过额外查询自动填充其Book列表
List<Account> accounts = accountMapper.selectListByQuery(query);

关键点:

  • leftJoin(Book.class)on(...) 方法定义了 AccountBook 之间的关联关系。
  • MyBatis-Flex 看到这个定义后,会执行以下步骤:
    1. 首先查询满足条件的 Account 列表。
    2. 然后根据 on 条件中定义的关联关系(Account.id = Book.account_id),再发起一次查询,获取所有相关的 Book
    3. 最后,自动将 Book 列表设置到对应 Account 对象的 books 属性中(需要你有这个属性)。

2. 基于 @Relation 注解的关联查询 (Auto)

这种方式是声明式的。你需要在实体类的字段上使用 @Relation 注解来定义关联关系,之后在查询时,MyBatis-Flex 会自动帮你完成数据的填充。这是最常用和推荐的方式。

@Relation 注解支持多种关联类型:

关联类型注解值说明
一对一RelationType.OneToOne例如:一个员工对应一个工位
多对一RelationType.ManyToOne例如:多本书属于同一个作者
一对多RelationType.OneToMany例如:一个作者拥有多本书
多对多RelationType.ManyToMany例如:一个学生选修多门课程,一门课程有多个学生
语法与示例

a. 一对多 (OneToMany)

Account 实体类中,定义一个 List<Book> 字段,并加上注解。

public class Account {private Long id;private String userName;// 关键:使用 @Relation 注解定义一对多关系@Relation(value = RelationType.OneToMany, // 关联类型targetField = "accountId" // 目标表(Book)中的关联字段)private List<Book> books;// ... getters and setters
}public class Book {private Long id;private String title;private Long accountId; // 这个字段与 Account.id 关联// ... getters and setters
}

查询时,直接使用普通查询即可,关联数据会自动填充:

// 无需在 QueryWrapper 中写 join,直接查
QueryWrapper query = QueryWrapper.create().where(Account::getUserName).eq("张三");List<Account> accounts = accountMapper.selectListByQuery(query);
// 此时,每个 accounts 中的 Account 对象,其 books 属性已被自动填充

b. 多对一 (ManyToOne)

Book 实体类中,定义一个 Account 字段。

public class Book {private Long id;private String title;private Long accountId;// 关键:使用 @Relation 注解定义多对一关系@Relation(value = RelationType.ManyToOne, // 关联类型targetField = "accountId", // 当前表(Book)中的关联字段// 指定目标表的关联字段,默认为 id,可省略targetFieldBind = "id" )private Account account;// ... getters and setters
}

查询书籍时,作者信息会自动填充:

List<Book> books = bookMapper.selectAll();
// 每个 Book 对象的 account 属性已被自动填充

c. 多对多 (ManyToMany)

多对多需要一个中间表。例如 Student, Course, StudentCourse

public class Student {private Long id;private String name;@Relation(value = RelationType.ManyToMany,// 中间表实体类targetTable = "tb_student_course",// 当前对象在中间表中的字段selfField = "id",// 当前对象在中间表中的字段(selfField)对应的中间表字段selfTargetField = "student_id",// 目标对象在中间表中的字段(targetField)对应的中间表字段targetTargetField = "course_id",// 目标表实体类targetTableField = "tb_course",// 目标对象的关联字段(通常是id)targetField = "id")private List<Course> courses;
}

3. 关联查询与条件

无论是哪种方式,你都可以轻松地添加关联表的查询条件。

使用 QueryWrapper 添加关联表条件:

QueryWrapper query = QueryWrapper.create().select().from(Account.class)// 定义关联关系.leftJoin(Book.class).on(Account::getId).eq(Book::getAccountId))// 主表条件.where(Account::getUserName).like("张")// 关联表条件!!!.and(Book::getPrice).gt(new BigDecimal("50.00")).and(Book::getStatus).eq(1);List<Account> accounts = accountMapper.selectListByQuery(query);

使用 @Relation 时,通过 extraCondition 添加额外条件:

public class Account {@Relation(value = RelationType.OneToMany,targetField = "accountId",// 额外条件:只查询状态为已发布的书籍extraCondition = "status = 1 and price > 50")private List<Book> publishedExpensiveBooks;
}

总结对比

特性基于 QueryWrapper基于 @Relation 注解
灵活性,可动态构建复杂关联,关系在代码中预先定义
便捷性,每次查询需手动编写关联,定义一次,随处使用
代码侵入性,不修改实体类,需要在实体类中添加注解和字段
适用场景动态、复杂的关联查询固定的、常见的关联关系

最佳实践建议:

  • 对于业务中固定的关联关系(如查询用户时总要显示他的订单),使用 @Relation 注解
  • 对于动态的、一次性的复杂关联查询(如根据多个动态条件关联查询),使用 QueryWrapper 手动关联
  • 灵活处理复杂关联使用基于QueryWrapper的关联查询 (Manual),配置即可实现关联查询使用基于 @Relation注解的关联查询 (Auto)
http://www.dtcms.com/a/352322.html

相关文章:

  • Dify 父子模式详解:如何实现模块化与高效协作
  • 学习做动画4.回转运动
  • Docker移动安装目录的两种实现方案
  • Qwen3-Coder-30B-A3B-Instruct AWQ 量化
  • 基于51单片机的DS18B20大棚温度监控系统
  • TRUST:a thermohydraulic software package for CFD simulations,开源多物理场数值模拟平台
  • Decode Global:以合规资质筑牢全球服务的根基
  • 数据中台的下一步,是数据飞轮吗?
  • Maya绑定基础:创建骨骼、修改骨骼
  • Android之腾讯TBS文件预览
  • JSX深度解析:不是HTML,胜似HTML的语法糖
  • Milvus介绍及多模态检索实践
  • 坑机介绍学习研究1
  • 美的组织架构再调整,微清事业部划入洗衣机事业部
  • uniapp 顶部tab + 占满剩余高度的内容区域swiper
  • 低空经济的中枢神经:实时视频链路如何支撑通信、导航、监视与气象
  • C/C++---浮点数与整形的转换,为什么使用sqrt函数时,要给参数加上一个极小的小数(如1e-6)
  • “喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
  • LangGraph
  • 研究4:海外休闲游戏,如何给主角做萌化处理
  • 基于SpringBoot的摄影跟拍约拍预约系统【2026最新】
  • C/C++---memset()初始化
  • 31.Encoder-Decoder(Seq2Seq)
  • MySQL8 排名窗口函数实战
  • 面试:Spring
  • 30.LSTM-长短时记忆单元
  • 抢红包案例加强版
  • 并行多核体系结构基础——共享存储并行编程(笔记)
  • 网络编程close学习
  • Java大厂面试实录:从Spring Boot到Kubernetes的全链路技术突围