withRelations() {
return new RelationsQuery<>(this);
}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/AbstractQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/AbstractQuery.java
deleted file mode 100644
index 3610dc87..00000000
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/AbstractQuery.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
- *
- * 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
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.activerecord.query;
-
-import com.mybatisflex.core.BaseMapper;
-import com.mybatisflex.core.activerecord.Model;
-import com.mybatisflex.core.paginate.Page;
-import com.mybatisflex.core.query.QueryWrapper;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * 抽象关联查询。
- *
- * @author 王帅
- * @since 2023-07-30
- */
-public abstract class AbstractQuery> {
-
- protected final Model model;
-
- protected AbstractQuery(Model model) {
- this.model = model;
- }
-
- /**
- * @return 主键
- */
- protected Object[] pkValues() {
- return model.pkValues();
- }
-
- /**
- * @return BaseMapper
- */
- protected BaseMapper baseMapper() {
- return model.baseMapper();
- }
-
- /**
- * @return QueryWrapper
- */
- protected QueryWrapper queryWrapper() {
- return model.queryWrapper();
- }
-
- /**
- * 根据实体类主键获取一条数据。
- *
- * @return 数据
- */
- public abstract T oneById();
-
- /**
- * 根据实体类主键获取一条数据,并封装为 {@link Optional} 返回。
- *
- * @return 数据
- */
- public Optional oneByIdOpt() {
- return Optional.ofNullable(oneById());
- }
-
- /**
- * 根据实体类主键获取一条数据。
- *
- * @return 数据
- */
- public abstract R oneByIdAs(Class asType);
-
- /**
- * 根据实体类主键获取一条数据,并封装为 {@link Optional} 返回。
- *
- * @return 数据
- */
- public Optional oneByIdAsOpt(Class asType) {
- return Optional.ofNullable(oneByIdAs(asType));
- }
-
- /**
- * 根据实体类构建的条件获取一条数据。
- *
- * @return 数据
- */
- public abstract T one();
-
- /**
- * 根据实体类构建的条件获取一条数据,返回的数据为 asType 类型。
- *
- * @param asType 接收数据类型
- * @return 数据
- */
- public abstract R oneAs(Class asType);
-
- /**
- * 根据实体类构建的条件获取一条数据,并封装为 {@link Optional} 返回。
- *
- * @return 数据
- */
- public Optional oneOpt() {
- return Optional.ofNullable(one());
- }
-
- /**
- * 根据实体类构建的条件获取一条数据,返回的数据为 asType 类型,并封装为 {@link Optional} 返回。
- *
- * @param asType 接收数据类型
- * @return 数据
- */
- public Optional oneOptAs(Class asType) {
- return Optional.ofNullable(oneAs(asType));
- }
-
- /**
- * 根据实体类构建的条件获取多条数据。
- *
- * @return 数据列表
- */
- public abstract List list();
-
- /**
- * 根据实体类构建的条件获取多条数据,返回的数据为 asType 类型。
- *
- * @param asType 接收数据类型
- * @return 数据列表
- */
- public abstract List listAs(Class asType);
-
- /**
- * 根据实体类构建的条件获取分页数据。
- *
- * @param page 分页对象
- * @return 分页数据
- */
- public abstract Page page(Page page);
-
- /**
- * 根据实体类构建的条件获取分页数据,返回的数据为 asType 类型。
- *
- * @param page 分页对象
- * @param asType 接收数据类型
- * @return 分页数据
- */
- public abstract Page pageAs(Page page, Class asType);
-
-}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/FieldsQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/FieldsQuery.java
index 0958d3af..3bc69815 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/FieldsQuery.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/FieldsQuery.java
@@ -17,19 +17,14 @@
package com.mybatisflex.core.activerecord.query;
import com.mybatisflex.core.activerecord.Model;
-import com.mybatisflex.core.field.FieldQuery;
import com.mybatisflex.core.field.FieldQueryManager;
import com.mybatisflex.core.field.QueryBuilder;
import com.mybatisflex.core.mybatis.MappedStatementTypes;
-import com.mybatisflex.core.paginate.Page;
-import com.mybatisflex.core.util.FieldWrapper;
+import com.mybatisflex.core.query.FieldsBuilder;
import com.mybatisflex.core.util.LambdaGetter;
-import com.mybatisflex.core.util.LambdaUtil;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
* 使用 {@code Fields Query} 的方式进行关联查询。
@@ -37,53 +32,34 @@ import java.util.Map;
* @author 王帅
* @since 2023-07-30
*/
-public class FieldsQuery> extends AbstractQuery {
-
- private final Map fieldQueryMap;
+public class FieldsQuery> extends FieldsBuilder {
public FieldsQuery(Model model) {
super(model);
- this.fieldQueryMap = new HashMap<>();
}
- /**
- * 设置属性对应的 {@code QueryWrapper} 查询。
- *
- * @param field 属性
- * @param builder {@code QueryWrapper} 构建
- * @param 属性类型
- * @return 属性查询构建
- */
+ @Override
public FieldsQuery fieldMapping(LambdaGetter field, QueryBuilder builder) {
- return fieldMapping(field, false, builder);
- }
-
- /**
- * 设置属性对应的 {@code QueryWrapper} 查询。
- *
- * @param field 属性
- * @param prevent 阻止对嵌套类属性的查询
- * @param builder {@code QueryWrapper} 构建
- * @param 属性类型
- * @return 属性查询构建
- */
- public FieldsQuery fieldMapping(LambdaGetter field, boolean prevent, QueryBuilder builder) {
- String fieldName = LambdaUtil.getFieldName(field);
- Class> entityClass = LambdaUtil.getImplClass(field);
- FieldQuery fieldQuery = new FieldQuery();
- fieldQuery.setPrevent(prevent);
- fieldQuery.setFieldName(fieldName);
- fieldQuery.setQueryBuilder(builder);
- fieldQuery.setEntityClass(entityClass);
- fieldQuery.setFieldWrapper(FieldWrapper.of(entityClass, fieldName));
- this.fieldQueryMap.put(entityClass.getName() + '#' + fieldName, fieldQuery);
+ super.fieldMapping(field, builder);
return this;
}
- /**
- * {@inheritDoc}
- */
@Override
+ public FieldsBuilder fieldMapping(LambdaGetter field, boolean prevent, QueryBuilder builder) {
+ super.fieldMapping(field, prevent, builder);
+ return this;
+ }
+
+ protected Object[] pkValues() {
+ // 懒加载,实际用到的时候才会生成 主键值
+ return ((Model) delegate).pkValues();
+ }
+
+ /**
+ * 根据主键查询一条数据。
+ *
+ * @return 一条数据
+ */
public T oneById() {
List entities = Collections.singletonList(baseMapper().selectOneById(pkValues()));
FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
@@ -91,9 +67,12 @@ public class FieldsQuery> extends AbstractQuery {
}
/**
- * {@inheritDoc}
+ * 根据主键查询一条数据,返回的数据为 asType 类型。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 一条数据
*/
- @Override
@SuppressWarnings("unchecked")
public R oneByIdAs(Class asType) {
try {
@@ -106,64 +85,4 @@ public class FieldsQuery> extends AbstractQuery {
}
}
- /**
- * {@inheritDoc}
- */
- @Override
- public T one() {
- List entities = Collections.singletonList(baseMapper().selectOneByQuery(queryWrapper()));
- FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
- return entities.get(0);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public R oneAs(Class asType) {
- List entities = Collections.singletonList(baseMapper().selectOneByQueryAs(queryWrapper(), asType));
- FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
- return entities.get(0);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List list() {
- List entities = baseMapper().selectListByQuery(queryWrapper());
- FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
- return entities;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List listAs(Class asType) {
- List entities = baseMapper().selectListByQueryAs(queryWrapper(), asType);
- FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
- return entities;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Page page(Page page) {
- baseMapper().paginate(page, queryWrapper());
- FieldQueryManager.queryFields(baseMapper(), page.getRecords(), fieldQueryMap);
- return page;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Page pageAs(Page page, Class asType) {
- baseMapper().paginateAs(page, queryWrapper(), asType);
- FieldQueryManager.queryFields(baseMapper(), page.getRecords(), fieldQueryMap);
- return page;
- }
-
}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/RelationsQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/RelationsQuery.java
index fe11e913..4f7a4b25 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/RelationsQuery.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/RelationsQuery.java
@@ -17,10 +17,8 @@
package com.mybatisflex.core.activerecord.query;
import com.mybatisflex.core.activerecord.Model;
-import com.mybatisflex.core.paginate.Page;
-import com.mybatisflex.core.relation.RelationManager;
-
-import java.util.List;
+import com.mybatisflex.core.query.RelationsBuilder;
+import com.mybatisflex.core.util.LambdaGetter;
/**
* 使用 {@code Relations Query} 的方式进行关联查询。
@@ -28,102 +26,59 @@ import java.util.List;
* @author 王帅
* @since 2023-07-30
*/
-public class RelationsQuery> extends AbstractQuery {
+public class RelationsQuery> extends RelationsBuilder {
public RelationsQuery(Model model) {
super(model);
}
- /**
- * 忽略查询部分 {@code Relations} 注解标记的属性。
- *
- * @param fields 属性
- * @return {@code Relations} 查询构建
- */
+ @Override
public RelationsQuery ignoreRelations(String... fields) {
- RelationManager.addIgnoreRelations(fields);
- return this;
- }
-
- /**
- * 设置父子关系查询中,默认的递归查询深度。
- *
- * @param maxDepth 查询深度
- * @return {@code Relations} 查询构建
- */
- public RelationsQuery maxDepth(int maxDepth) {
- RelationManager.setMaxDepth(maxDepth);
- return this;
- }
-
- /**
- * 添加额外的 {@code Relations} 查询条件。
- *
- * @param key 键
- * @param value 值
- * @return {@code Relations} 查询构建
- */
- public RelationsQuery extraConditionParam(String key, Object value) {
- RelationManager.addExtraConditionParam(key, value);
+ super.ignoreRelations(fields);
return this;
}
@Override
+ public RelationsQuery ignoreRelations(LambdaGetter... fields) {
+ super.ignoreRelations(fields);
+ return this;
+ }
+
+ @Override
+ public RelationsQuery maxDepth(int maxDepth) {
+ super.maxDepth(maxDepth);
+ return this;
+ }
+
+ @Override
+ public RelationsQuery extraConditionParam(String key, Object value) {
+ super.extraConditionParam(key, value);
+ return this;
+ }
+
+ protected Object[] pkValues() {
+ // 懒加载,实际用到的时候才会生成 主键值
+ return ((Model) delegate).pkValues();
+ }
+
+ /**
+ * 根据主键查询一条数据。
+ *
+ * @return 一条数据
+ */
public T oneById() {
return baseMapper().selectOneWithRelationsById(pkValues());
}
- @Override
+ /**
+ * 根据主键查询一条数据,返回的数据为 asType 类型。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 一条数据
+ */
public R oneByIdAs(Class asType) {
return baseMapper().selectOneWithRelationsByIdAs(pkValues(), asType);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public T one() {
- return baseMapper().selectOneWithRelationsByQuery(queryWrapper());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public R oneAs(Class asType) {
- return baseMapper().selectOneWithRelationsByQueryAs(queryWrapper(), asType);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List list() {
- return baseMapper().selectListWithRelationsByQuery(queryWrapper());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List listAs(Class asType) {
- return baseMapper().selectListWithRelationsByQueryAs(queryWrapper(), asType);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Page page(Page page) {
- return baseMapper().paginateWithRelations(page, queryWrapper());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Page pageAs(Page page, Class asType) {
- return baseMapper().paginateWithRelationsAs(page, queryWrapper(), asType);
- }
-
}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java
index 1e3e9c47..eb3ee12a 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceManager.java
@@ -21,6 +21,9 @@ import org.apache.ibatis.logging.LogFactory;
import javax.sql.DataSource;
import java.lang.reflect.Method;
+/**
+ * @author michael
+ */
public class DataSourceManager {
private static DataSourceDecipher decipher;
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/FlexDataSource.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/FlexDataSource.java
index 8dd60a95..2886d8cd 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/FlexDataSource.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/FlexDataSource.java
@@ -49,8 +49,13 @@ public class FlexDataSource extends AbstractDataSource {
private final DataSource defaultDataSource;
public FlexDataSource(String dataSourceKey, DataSource dataSource) {
+ this(dataSourceKey, dataSource, true);
+ }
- DataSourceManager.decryptDataSource(dataSource);
+ public FlexDataSource(String dataSourceKey, DataSource dataSource, boolean needDecryptDataSource) {
+ if (needDecryptDataSource) {
+ DataSourceManager.decryptDataSource(dataSource);
+ }
this.defaultDataSourceKey = dataSourceKey;
this.defaultDataSource = dataSource;
@@ -61,11 +66,19 @@ public class FlexDataSource extends AbstractDataSource {
}
public void addDataSource(String dataSourceKey, DataSource dataSource) {
- DataSourceManager.decryptDataSource(dataSource);
+ addDataSource(dataSourceKey, dataSource, true);
+ }
+
+
+ public void addDataSource(String dataSourceKey, DataSource dataSource, boolean needDecryptDataSource) {
+ if (needDecryptDataSource) {
+ DataSourceManager.decryptDataSource(dataSource);
+ }
dataSourceMap.put(dataSourceKey, dataSource);
dbTypeHashMap.put(dataSourceKey, DbTypeUtil.getDbType(dataSource));
}
+
public void removeDatasource(String dataSourceKey) {
dataSourceMap.remove(dataSourceKey);
dbTypeHashMap.remove(dataSourceKey);
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/AbstractQueryBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/AbstractQueryBuilder.java
new file mode 100644
index 00000000..eacfc83a
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/AbstractQueryBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.query;
+
+import com.mybatisflex.core.BaseMapper;
+
+/**
+ * 抽象关联查询。
+ *
+ * @author 王帅
+ * @since 2023-08-08
+ */
+public abstract class AbstractQueryBuilder implements ChainQuery {
+
+ protected final MapperQueryChain delegate;
+
+ protected AbstractQueryBuilder(MapperQueryChain delegate) {
+ this.delegate = delegate;
+ }
+
+ /**
+ * @return BaseMapper
+ */
+ protected BaseMapper baseMapper() {
+ return delegate.baseMapper();
+ }
+
+ /**
+ * @return QueryWrapper
+ */
+ protected QueryWrapper queryWrapper() {
+ return delegate.toQueryWrapper();
+ }
+
+}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/ChainQuery.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/ChainQuery.java
new file mode 100644
index 00000000..35e367e8
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/ChainQuery.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.query;
+
+import com.mybatisflex.core.paginate.Page;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ *
链式查询接口。
+ *
+ *
该接口定义了通用的链式查询方法:
+ *
+ * - one: 查询一条数据。
+ *
- list: 查询多条数据。
+ *
- page: 分页查询数据。
+ *
+ *
+ * @param 实体类类型
+ * @author 王帅
+ * @since 2023-08-08
+ */
+public interface ChainQuery {
+
+ /**
+ * 获取一条数据。
+ *
+ * @return 一条数据
+ */
+ T one();
+
+ /**
+ * 获取一条数据,返回的数据为 asType 类型。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 一条数据
+ */
+ R oneAs(Class asType);
+
+ /**
+ * 获取一条数据,并封装为 {@link Optional} 返回。
+ *
+ * @return 一条数据
+ */
+ default Optional oneOpt() {
+ return Optional.ofNullable(one());
+ }
+
+ /**
+ * 获取一条数据,返回的数据为 asType 类型,并封装为 {@link Optional} 返回。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 一条数据
+ */
+ default Optional oneAsOpt(Class asType) {
+ return Optional.ofNullable(oneAs(asType));
+ }
+
+ /**
+ * 获取多条数据。
+ *
+ * @return 数据列表
+ */
+ List list();
+
+ /**
+ * 获取多条数据,返回的数据为 asType 类型。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 数据列表
+ */
+ List listAs(Class asType);
+
+ /**
+ * 获取分页数据。
+ *
+ * @param page 分页对象
+ * @return 分页数据
+ */
+ Page page(Page page);
+
+ /**
+ * 获取分页数据,返回的数据为 asType 类型。
+ *
+ * @param page 分页对象
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 分页数据
+ */
+ Page pageAs(Page page, Class asType);
+
+}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/FieldsBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/FieldsBuilder.java
new file mode 100644
index 00000000..1eb980da
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/FieldsBuilder.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.query;
+
+import com.mybatisflex.core.field.FieldQuery;
+import com.mybatisflex.core.field.FieldQueryManager;
+import com.mybatisflex.core.field.QueryBuilder;
+import com.mybatisflex.core.paginate.Page;
+import com.mybatisflex.core.util.FieldWrapper;
+import com.mybatisflex.core.util.LambdaGetter;
+import com.mybatisflex.core.util.LambdaUtil;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 使用 {@code Fields Query} 的方式进行关联查询。
+ *
+ * @author 王帅
+ * @since 2023-08-08
+ */
+public class FieldsBuilder extends AbstractQueryBuilder {
+
+ protected final Map fieldQueryMap;
+
+ public FieldsBuilder(MapperQueryChain delegate) {
+ super(delegate);
+ this.fieldQueryMap = new HashMap<>();
+ }
+
+ /**
+ * 设置属性对应的 {@code QueryWrapper} 查询。
+ *
+ * @param field 属性
+ * @param builder {@code QueryWrapper} 构建
+ * @param 属性类型
+ * @return 属性查询构建
+ */
+ public FieldsBuilder fieldMapping(LambdaGetter field, QueryBuilder builder) {
+ return fieldMapping(field, false, builder);
+ }
+
+ /**
+ * 设置属性对应的 {@code QueryWrapper} 查询。
+ *
+ * @param field 属性
+ * @param prevent 阻止对嵌套类属性的查询
+ * @param builder {@code QueryWrapper} 构建
+ * @param 属性类型
+ * @return 属性查询构建
+ */
+ public FieldsBuilder fieldMapping(LambdaGetter field, boolean prevent, QueryBuilder builder) {
+ String fieldName = LambdaUtil.getFieldName(field);
+ Class> entityClass = LambdaUtil.getImplClass(field);
+ FieldQuery fieldQuery = new FieldQuery();
+ fieldQuery.setPrevent(prevent);
+ fieldQuery.setFieldName(fieldName);
+ fieldQuery.setQueryBuilder(builder);
+ fieldQuery.setEntityClass(entityClass);
+ fieldQuery.setFieldWrapper(FieldWrapper.of(entityClass, fieldName));
+ this.fieldQueryMap.put(entityClass.getName() + '#' + fieldName, fieldQuery);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T one() {
+ List entities = Collections.singletonList(baseMapper().selectOneByQuery(queryWrapper()));
+ FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
+ return entities.get(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public R oneAs(Class asType) {
+ List entities = Collections.singletonList(baseMapper().selectOneByQueryAs(queryWrapper(), asType));
+ FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
+ return entities.get(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List list() {
+ List entities = baseMapper().selectListByQuery(queryWrapper());
+ FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
+ return entities;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List listAs(Class asType) {
+ List entities = baseMapper().selectListByQueryAs(queryWrapper(), asType);
+ FieldQueryManager.queryFields(baseMapper(), entities, fieldQueryMap);
+ return entities;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Page page(Page page) {
+ baseMapper().paginate(page, queryWrapper());
+ FieldQueryManager.queryFields(baseMapper(), page.getRecords(), fieldQueryMap);
+ return page;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Page pageAs(Page page, Class asType) {
+ baseMapper().paginateAs(page, queryWrapper(), asType);
+ FieldQueryManager.queryFields(baseMapper(), page.getRecords(), fieldQueryMap);
+ return page;
+ }
+
+}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/MapperQueryChain.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/MapperQueryChain.java
new file mode 100644
index 00000000..31886606
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/MapperQueryChain.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.query;
+
+import com.mybatisflex.core.BaseMapper;
+import com.mybatisflex.core.paginate.Page;
+import com.mybatisflex.core.util.SqlUtil;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ *
链式 {@link BaseMapper} 查询。
+ *
+ *
要求实现类除了包含有 {@link BaseMapper} 接口的引用外,还必须具有 {@link QueryWrapper}
+ * 的查询条件构建功能。在使用时:
+ *
+ * - 通过 {@link #baseMapper()} 获取该实现类对应的 {@link BaseMapper} 引用。
+ *
- 通过 {@link #toQueryWrapper()} 将该实现类转换为 {@link QueryWrapper} 对象。
+ *
+ *
+ * @param 实体类类型
+ * @author 王帅
+ * @since 2023-08-08
+ */
+public interface MapperQueryChain extends ChainQuery {
+
+ /**
+ * 该实现类对应的 {@link BaseMapper} 对象。
+ *
+ * @return {@link BaseMapper}
+ */
+ BaseMapper baseMapper();
+
+ /**
+ * 将该实现类转换为 {@link QueryWrapper} 对象。
+ *
+ * @return {@link QueryWrapper}
+ */
+ QueryWrapper toQueryWrapper();
+
+ /**
+ * 查询数据数量。
+ *
+ * @return 数据数量
+ */
+ default long count() {
+ return baseMapper().selectCountByQuery(toQueryWrapper());
+ }
+
+ /**
+ * 判断数据是否存在。
+ *
+ * @return {@code true} 数据存在,{@code false} 数据不存在
+ */
+ default boolean exists() {
+ return SqlUtil.toBool(count());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ default T one() {
+ return baseMapper().selectOneByQuery(toQueryWrapper());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ default R oneAs(Class asType) {
+ return baseMapper().selectOneByQueryAs(toQueryWrapper(), asType);
+ }
+
+ /**
+ * 获取第一列,且第一条数据。
+ *
+ * @return 第一列数据
+ */
+ default Object obj() {
+ return baseMapper().selectObjectByQuery(toQueryWrapper());
+ }
+
+ /**
+ * 获取第一列,且第一条数据并转换为指定类型,比如 {@code Long}, {@code String} 等。
+ *
+ * @param asType 接收数据类型
+ * @param 接收数据类型
+ * @return 第一列数据
+ */
+ default R objAs(Class asType) {
+ return baseMapper().selectObjectByQueryAs(toQueryWrapper(), asType);
+ }
+
+ /**
+ * 获取第一列,且第一条数据,并封装为 {@link Optional} 返回。
+ *
+ * @return 第一列数据
+ */
+ default Optional