mybatis-flex/docs/zh/base/field-query.md

3.3 KiB
Raw Blame History

一对多、多对一

在很多场景下,我们可能会用到 一对多一对一多对一多对多等场景的关联查询MyBatis-Flex 内置了相关的方法,用于支持此类场景。

代码示例(多对多)

以下是文章的示例,一篇文章可能归属于多个分类,一个类可以有多篇文章,需要用到中间表 article_category_mapping

public class Article {
    private Long id;
    private String title;
    private String content;

    //文章的归属分类,可能是 1 个或者多个
    private List<Category> categories;

    //getter setter
}

查询代码如下:

QueryWrapper queryWrapper = QueryWrapper.create()
        .select().form(ARTICLE)
        .where(ARTICLE.id.ge(100));

List<Article> articles = mapper.selectListByQuery(queryWrapper
    , fieldQueryBuilder -> fieldQueryBuilder
        .field(Article::getCategories) // 或者 .field("categories")
        .queryWrapper(article -> QueryWrapper.create()
            .select().from(CATEGORY)
            .where(CATEGORY.id.in(
                    select("category_id").from("article_category_mapping")
                    .where("article_id = ?", article.getId())
            )
        )
    );

通过以上代码可以看出,Article.categories 字段的结果,来源于 queryWrapper() 方法构建的 QueryWrapper

其原理是MyBatis-Flex 的内部逻辑是先查询出 Article 的数据,然后再根据 Article 构建出新的 SQL查询分类并赋值给 Article.categories 假设 Article 有 10 条数据,那么最终会进行 11 次数据库查询。

查询的 SQL 大概如下:

select * from tb_article where id  >= 100;

-- 以上 SQL 得到结果后,再执行查询分类的 SQL如下
select * from tb_category where id in 
(select category_id from article_category_mapping where article_id = 100);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 101);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 102);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 103);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 104);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 105);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 106);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 107);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 108);

select * from tb_category where id in
(select category_id from article_category_mapping where article_id = 109);

其他场景

通过以上内容看出,Article 的任何属性,都是可以通过传入 FieldQueryBuilder 来构建 QueryWrapper 进行再次查询, 这些不仅仅只适用于 一对多一对一多对一多对多等场景。任何 Article 对象里的属性,需要二次查询赋值的,都是可以通过这种方式进行。