mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 09:38:26 +08:00
88 lines
3.3 KiB
Markdown
88 lines
3.3 KiB
Markdown
# 一对多、多对一
|
||
|
||
在很多场景下,我们可能会用到 `一对多`、`一对一`、`多对一`、`多对多`等场景的关联查询,MyBatis-Flex 内置了相关的方法,用于支持此类场景。
|
||
|
||
## 代码示例(多对多)
|
||
|
||
以下是文章的示例,一篇文章可能归属于多个分类,一个类可以有多篇文章,需要用到中间表 `article_category_mapping`。
|
||
|
||
```java
|
||
public class Article {
|
||
private Long id;
|
||
private String title;
|
||
private String content;
|
||
|
||
//文章的归属分类,可能是 1 个或者多个
|
||
private List<Category> categories;
|
||
|
||
//getter setter
|
||
}
|
||
```
|
||
|
||
查询代码如下:
|
||
|
||
```java {10-14}
|
||
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")
|
||
.type(Category.class) //非集合,自动读取 type,可以不指定 type
|
||
.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 大概如下:
|
||
|
||
```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` 对象里的属性,需要二次查询赋值的,都是可以通过这种方式进行。 |