MyBatis-Flex多表关联查询指南分享

 更新时间:2026年05月15日 10:38:30   作者:友莘居士  
本文介绍了MyBatis-Flex的多表关联查询功能,包括基于QueryWrapper的动态关联查询和基于@Relation注解的静态关联查询,通过示例展示了如何实现不同类型的关联关系,并对比了两种方式的特点和适用场景,最后给出了最佳实践建议

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)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot多模块包扫描问题的解决方法

    springboot多模块包扫描问题的解决方法

    这篇文章主要介绍了springboot多模块包扫描问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • SpringBoot开启Swagger并配置基本信息方式

    SpringBoot开启Swagger并配置基本信息方式

    这篇文章主要介绍了SpringBoot开启Swagger并配置基本信息方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 聊聊Spring Boot如何配置多个Kafka数据源

    聊聊Spring Boot如何配置多个Kafka数据源

    这篇文章主要介绍了Spring Boot配置多个Kafka数据源的相关知识,包括生产者、消费者配置,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-10-10
  • java版十大排序经典算法:完整代码(2)

    java版十大排序经典算法:完整代码(2)

    优秀的文章也不少,但是Java完整版的好像不多,我把所有的写一遍巩固下,同时也真诚的希望阅读到这篇文章的小伙伴们可以自己去从头敲一遍,不要粘贴复制!希望我的文章对你有所帮助,每天进步一点点
    2021-07-07
  • Spring JPA联表查询之OneToMany源码解析

    Spring JPA联表查询之OneToMany源码解析

    这篇文章主要为大家介绍了Spring JPA联表查询之OneToMany源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • SpringBoot学习之全局异常处理设置(返回JSON)

    SpringBoot学习之全局异常处理设置(返回JSON)

    本篇文章主要介绍了SpringBoot学习之全局异常处理设置(返回JSON),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • java 实现web项目启动加载properties属性文件

    java 实现web项目启动加载properties属性文件

    这篇文章主要介绍了java 实现web项目启动加载properties属性文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • springboot 重定向方式(redirect前缀)

    springboot 重定向方式(redirect前缀)

    这篇文章主要介绍了springboot 重定向方式(redirect前缀),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 利用idea快速搭建一个spring-cloud(图文)

    利用idea快速搭建一个spring-cloud(图文)

    本文主要介绍了idea快速搭建一个spring-cloud,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Spring Boot 中事务的用法示例详解

    Spring Boot 中事务的用法示例详解

    本文详细介绍了Spring Boot中事务管理的使用方法,包括事务的基本概念、配置、传播行为、隔离级别以及回滚机制,通过使用@Transactional注解,可以方便地实现事务的控制,文章还讨论了事务方法的可见性、自我调用问题以及超时设置等注意事项,感兴趣的朋友一起看看吧
    2025-02-02

最新评论