feat: 新增 一对多、多对一 查询功能

This commit is contained in:
开源海哥 2023-05-24 13:25:56 +08:00
parent 12a4efd121
commit 138a805ae7
5 changed files with 216 additions and 0 deletions

View File

@ -61,6 +61,7 @@ export default defineConfig({
{text: '增、删、改', link: '/zh/base/add-delete-update'}, {text: '增、删、改', link: '/zh/base/add-delete-update'},
{text: '查询和分页', link: '/zh/base/query'}, {text: '查询和分页', link: '/zh/base/query'},
{text: '批量操作', link: '/zh/base/batch'}, {text: '批量操作', link: '/zh/base/batch'},
{text: '一对多、多对一', link: '/zh/base/field-query'},
{text: 'QueryWrapper', link: '/zh/base/querywrapper'}, {text: 'QueryWrapper', link: '/zh/base/querywrapper'},
{text: 'Db + Row', link: '/zh/base/db-row'}, {text: 'Db + Row', link: '/zh/base/db-row'},
{text: 'IService', link: '/zh/base/service'}, {text: 'IService', link: '/zh/base/service'},

View File

@ -0,0 +1,88 @@
# 一对多、多对一
在很多场景下,我们可能会用到 `一对多``一对一``多对一`等场景的关联查询MyBatis-Flex 内置了相关的方法,用于支持此类场景。
## 代码示例
以下是文章的示例,一篇文章可能归属于多个分类。
```java
public class Article {
private Long id;
private String title;
private String content;
//文章的归属分类,可能是 1 个或者多个
private List<Category> categories;
//getter setter
}
```
查询代码如下:
```java {10-13}
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
.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` 对象里的属性,需要二次查询赋值的,都是可以通过这种方式进行。

View File

@ -0,0 +1,51 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.field;
import com.mybatisflex.core.query.QueryWrapper;
import java.io.Serializable;
public class FieldQuery implements Serializable {
private String field;
private Class<?> mappingType;
private QueryWrapper queryWrapper;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public Class<?> getMappingType() {
return mappingType;
}
public void setMappingType(Class<?> mappingType) {
this.mappingType = mappingType;
}
public QueryWrapper getQueryWrapper() {
return queryWrapper;
}
public void setQueryWrapper(QueryWrapper queryWrapper) {
this.queryWrapper = queryWrapper;
}
}

View File

@ -0,0 +1,54 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.field;
import com.mybatisflex.core.util.LambdaGetter;
import com.mybatisflex.core.util.LambdaUtil;
import java.io.Serializable;
public class FieldQueryBuilder<T> implements Serializable {
private T entity;
private FieldQuery fieldQuery = new FieldQuery();
public FieldQueryBuilder(T entity) {
this.entity = entity;
}
public FieldQueryBuilder<T> field(String field){
fieldQuery.setField(field);
return this;
}
public FieldQueryBuilder<T> field(LambdaGetter<T> fn){
return field(LambdaUtil.getFieldName(fn));
}
public FieldQueryBuilder<T> type(Class<?> mappingType){
fieldQuery.setMappingType(mappingType);
return this;
}
public FieldQueryBuilder<T> queryWrapper(QueryBuilder<T> fun){
fieldQuery.setQueryWrapper(fun.build(entity));
return this;
}
public FieldQuery build() {
return fieldQuery;
}
}

View File

@ -0,0 +1,22 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.field;
import com.mybatisflex.core.query.QueryWrapper;
public interface QueryBuilder<T> {
QueryWrapper build(T entity);
}