MyBatis 多表查询应该这么玩,MyBatis-Flex v1.3.3 发布

来源: 投稿
作者: 开源海哥
2023-06-01 09:59:00

Mybatis-Flex 是一个优雅的 Mybatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库,其内置的 QueryWrapper 帮助我们极大的减少了 SQL 编写的工作的同时,减少出错的可能性。

总而言之,Mybatis-Flex 能够极大地提高我们的开发效率和开发体验,让我们有更多的时间专注于自己的事情。

MyBatis-Flex  v1.3.3 主要是增强了多表查询的功能,假设有 tb_account 用户表和 tb_article 文章表,他们的字段分别如下:

CREATE TABLE IF NOT EXISTS `tb_account`
(
    `id`        INTEGER PRIMARY KEY auto_increment,
    `user_name` VARCHAR(100),
    `age`       Integer,
    `birthday`  DATETIME
);

CREATE TABLE IF NOT EXISTS `tb_article`
(
    `id`         INTEGER PRIMARY KEY auto_increment,
    `account_id` Integer,
    `title`      VARCHAR(100),
    `content`    text
);

MyBatis-Flex 提供了 3 中方式,可以进行关联查询:

方式 1

1、定义 ArticleDTO 类,ArticleDTO 里定义 tb_account 表的字段映射。

public class ArticleDTO {

    private Long id;
    private Long accountId;
    private String title;
    private String content;
    
    //以下用户相关字段
    private String userName;
    private int age;
    private Date birthday;
}

然后直接通过 QueryWrapper 查询,代码如下:

QueryWrapper query = QueryWrapper.create()
        .select(ARTICLE.ALL_COLUMNS)
        .select(ACCOUNT.USER_NAME,ACCOUNT.AGE,ACCOUNT.BIRTHDAY)
        .from(ARTICLE)
        .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID));

List<ArticleDTO> results = mapper.selectListByQueryAs(query, ArticleDTO.class);
System.out.println(results);

方式 2

假设 ArticleDTO 定义的属性和 数据库字段不一致时,例如:

public class ArticleDTO {

  private Long id;
  private Long accountId;
  private String title;
  private String content;

  //以下用户字段 和 用户表定义的列不一致,表定义的列为 user_name
  private String authorName;
  private int authorAge;
  private Date birthday;
}

那么, QueryWrapper 需要添加 as,修改如下:

QueryWrapper query = QueryWrapper.create()
    .select(ARTICLE.ALL_COLUMNS)
    .select(ACCOUNT.USER_NAME.as(ArticleDTO::getAuthorName)
            ,ACCOUNT.AGE.as(ArticleDTO::getAuthorAge)
            ,ACCOUNT.BIRTHDAY
    )
    .from(ARTICLE)
    .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID));

List<ArticleDTO> results = mapper.selectListByQueryAs(query, ArticleDTO.class);
System.out.println(results);

方式 3 

1、在 ArticleDTO 直接定义 Account 实体类属性。 例如:

public class ArticleDTO {

    private Long id;
    private Long accountId;
    private String title;
    private String content;
    
    //直接定义 Account 对象
    private Account account;
}

查询方式和方式1一样,使用 QueryWrapper 构建 left join 查询,查询结果通过 ArticleDTO 类型接收。

QueryWrapper query = QueryWrapper.create()
        .select(ARTICLE.ALL_COLUMNS)
        .select(ACCOUNT.USER_NAME,ACCOUNT.AGE,ACCOUNT.BIRTHDAY)
        .from(ARTICLE)
        .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID));

List<ArticleDTO> results = mapper.selectListByQueryAs(query, ArticleDTO.class);
System.out.println(results);

一对多查询

在以上的例子中,一个作者可能有多篇文档,假设 Account 的属性定义如下:

public class Article {
    private Long id;
    private String userName;
    private int age;

    //一个作者有多篇文章
    private List<Article> articles;
}

那么,查询代码如下:

QueryWrapper query = QueryWrapper.create()
        .select().form(ACCOUNT);

List<Account> accounts = mapper.selectListByQuery(query
    , fieldQueryBuilder -> fieldQueryBuilder
        .field(Account::getArticles) // 或者 .field("articles")
        .queryWrapper(account -> QueryWrapper.create()
            .select().from(ARTICLE)
            .where(ARTICLE.ACCOUNT_ID.eq(account.getId())
            )
        )
    );

知识点

MyBatis-Flex 的关联子查询,和 JPA 等其他第三方框架有很大的差异,比如 JPA 是通过配置来构建查询 SQL,其构建生成的 SQL 对于用户来说是不透明的。 因此,用户几乎无法对 JPA 的注解生成 SQL 优化。

而 MyBatis-Flex 关联子查询的 SQL 完全是由用户构建的,因此会更加灵活,更加有利于我们进行 SQL 优化。在子查询中,有很多的场景,JPA 一对一、 一对多等等不同的场景给出了不同的注解、以及参数,导致用户的学习成本非常高。另外,在很多业务场景下, 比如多租户、逻辑删除、等等 MyBatis-Flex 都是内部自动处理,而 JPA 通过注解的实现则是非常麻烦。

对 MyBatis-Flex 来说,学习成本是非常低的,在构建子查询时,只需要明白为哪个字段、通过什么样的 SQL 查询就可以了,以下是示例:

因此,在 MyBatis-Flex 的设计中,无论是一对多、多对一、多对多... 还是其他任何一种场景,其逻辑都是一样的。更多的文档请参考:https://mybatis-flex.com/zh/base/field-query.html

MyBatis-Flex v1.3.3 更新如下:

 

进一步了解 MyBatis-Flex 框架,请参考一下链接:

和其他框架对比请参考:

 

感谢大家关注 MyBatis-Flex ,让我们一起携手,打造新一代的 MyBatis 增强框架。 

展开阅读全文
点击加入讨论🔥(13) 发布并加入讨论🔥
本篇精彩评论
习惯在 xml 写 sql 了,一时反应不过来,这是正常的。在 xml 里写 sql 有很多弊端: 1 各种 if 条件判断、sql 拼接在 xml 里显得非常啰嗦;2 几乎无法自适应数据库,换一个数据库几乎需要从写一遍,当一个应用需要适配多个数据库的时候,一般都是需要多分 xml;3 无法进行重构,数据库字段在应用的升级过程中,对字段的新增、删除和修改,在 xml 里根本无法感知,唯一的感知途径是出现了异常,而通过 QueryWrapper 构建 sql,就能很好的利用编辑器的重构功能进行批量重构和错误感知;4、在 xml 里,除了编写 sql 以外,我们还是做其他很多的配置,比如需要编写 resultMap,需要注意 $ 和 # 号的各种区别,需要保持 xml 定义的 id 和 namespace 和 java对应 等等;这些总总问题,在 flex 几乎都被消灭了,总之,在 xml 里编写 sql 是 “上个时代” 的产物。
2023-06-01 12:05
2
举报
怎么说呢,直接在xml写关联不香吗?碰到复杂业务这么写不整死人?
2023-06-01 11:40
2
举报
我还以为只是我一个人讨厌mybatis, 我用过.net python的orm框架都没有像mybatis这么奇葩的在xml写sql的工具, mybatis开发效率确实太低了, 不用动不动就说什么互联网, 现在绝大多数项目都是中小项目多, 其实JAP都已经可以胜任很多项目了
2023-06-01 16:54
1
举报
13 评论
6 收藏
分享
返回顶部
顶部