001/*
002 *  Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core;
017
018import com.mybatisflex.core.constant.FuncName;
019import com.mybatisflex.core.exception.FlexAssert;
020import com.mybatisflex.core.field.FieldQueryBuilder;
021import com.mybatisflex.core.mybatis.MappedStatementTypes;
022import com.mybatisflex.core.paginate.Page;
023import com.mybatisflex.core.provider.EntitySqlProvider;
024import com.mybatisflex.core.query.*;
025import com.mybatisflex.core.row.Row;
026import com.mybatisflex.core.table.TableInfo;
027import com.mybatisflex.core.table.TableInfoFactory;
028import com.mybatisflex.core.util.*;
029import org.apache.ibatis.annotations.*;
030import org.apache.ibatis.builder.annotation.ProviderContext;
031import org.apache.ibatis.cursor.Cursor;
032
033import java.io.Serializable;
034import java.util.*;
035import java.util.function.Consumer;
036
037import static com.mybatisflex.core.query.QueryMethods.count;
038
039/**
040 * 通用 Mapper 接口。
041 *
042 * @param <T> 实体类类型
043 * @author 开源海哥
044 * @author 庄佳彬
045 * @author 闵柳华
046 * @author 王帅
047 * @author yangs
048 * @author lhzsdnu
049 */
050@SuppressWarnings({"varargs", "unchecked", "unused"})
051public interface BaseMapper<T> {
052
053    /**
054     * 默认批量处理切片数量。
055     */
056    int DEFAULT_BATCH_SIZE = 1000;
057
058    // === 增(insert) ===
059
060    /**
061     * 插入实体类数据,不忽略 {@code null} 值。
062     *
063     * @param entity 实体类
064     * @return 受影响的行数
065     */
066    default int insert(T entity) {
067        return insert(entity, false);
068    }
069
070    /**
071     * 插入实体类数据,但是忽略 {@code null} 的数据,只对有值的内容进行插入。
072     * 这样的好处是数据库已经配置了一些默认值,这些默认值才会生效。
073     *
074     * @param entity 实体类
075     * @return 受影响的行数
076     */
077    default int insertSelective(T entity) {
078        return insert(entity, true);
079    }
080
081    /**
082     * 插入实体类数据。
083     *
084     * @param entity      实体类
085     * @param ignoreNulls 是否忽略 {@code null} 值
086     * @return 受影响的行数
087     * @see com.mybatisflex.core.provider.EntitySqlProvider#insert(Map, ProviderContext)
088     */
089    @InsertProvider(type = EntitySqlProvider.class, method = "insert")
090    int insert(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
091
092    /**
093     * 插入带有主键的实体类,不忽略 {@code null} 值。
094     *
095     * @param entity 实体类
096     * @return 受影响的行数
097     */
098    default int insertWithPk(T entity) {
099        return insertWithPk(entity, false);
100    }
101
102    /**
103     * 插入带有主键的实体类,忽略 {@code null} 值。
104     *
105     * @param entity 实体类
106     * @return 受影响的行数
107     */
108    default int insertSelectiveWithPk(T entity) {
109        return insertWithPk(entity, true);
110    }
111
112    /**
113     * 带有主键的插入,此时实体类不会经过主键生成器生成主键。
114     *
115     * @param entity      带有主键的实体类
116     * @param ignoreNulls 是否忽略 {@code null} 值
117     * @return 受影响的行数
118     * @see com.mybatisflex.core.provider.EntitySqlProvider#insertWithPk(Map, ProviderContext)
119     */
120    @InsertProvider(type = EntitySqlProvider.class, method = "insertWithPk")
121    int insertWithPk(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
122
123    /**
124     * 批量插入实体类数据,只会根据第一条数据来构建插入的字段内容。
125     *
126     * @param entities 插入的数据列表
127     * @return 受影响的行数
128     * @see com.mybatisflex.core.provider.EntitySqlProvider#insertBatch(Map, ProviderContext)
129     * @see com.mybatisflex.core.FlexConsts#METHOD_INSERT_BATCH
130     */
131    @InsertProvider(type = EntitySqlProvider.class, method = FlexConsts.METHOD_INSERT_BATCH)
132    int insertBatch(@Param(FlexConsts.ENTITIES) List<T> entities);
133
134    /**
135     * 批量插入实体类数据,按 size 切分。
136     *
137     * @param entities 插入的数据列表
138     * @param size     切分大小
139     * @return 受影响的行数
140     */
141    default int insertBatch(List<T> entities, int size) {
142        if (size <= 0) {
143            size = DEFAULT_BATCH_SIZE;
144        }
145        int sum = 0;
146        int entitiesSize = entities.size();
147        int maxIndex = entitiesSize / size + (entitiesSize % size == 0 ? 0 : 1);
148        for (int i = 0; i < maxIndex; i++) {
149            List<T> list = entities.subList(i * size, Math.min(i * size + size, entitiesSize));
150            sum += insertBatch(list);
151        }
152        return sum;
153    }
154
155    /**
156     * 插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都不会忽略 {@code null} 值。
157     *
158     * @param entity 实体类
159     * @return 受影响的行数
160     */
161    default int insertOrUpdate(T entity) {
162        return insertOrUpdate(entity, false);
163    }
164
165    /**
166     * 插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都会忽略 {@code null} 值。
167     *
168     * @param entity 实体类
169     * @return 受影响的行数
170     */
171    default int insertOrUpdateSelective(T entity) {
172        return insertOrUpdate(entity, true);
173    }
174
175    /**
176     * 插入或者更新,若主键有值,则更新,若没有主键值,则插入。
177     *
178     * @param entity      实体类
179     * @param ignoreNulls 是否忽略 {@code null} 值
180     * @return 受影响的行数
181     */
182    default int insertOrUpdate(T entity, boolean ignoreNulls) {
183        TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass());
184        Object[] pkArgs = tableInfo.buildPkSqlArgs(entity);
185        if (pkArgs.length == 0 || pkArgs[0] == null) {
186            return insert(entity, ignoreNulls);
187        } else {
188            return update(entity, ignoreNulls);
189        }
190    }
191
192    // === 删(delete) ===
193
194    /**
195     * 根据主键删除数据。如果是多个主键的情况下,需要传入数组,例如:{@code new Integer[]{100,101}}。
196     *
197     * @param id 主键数据
198     * @return 受影响的行数
199     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteById(Map, ProviderContext)
200     */
201    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteById")
202    int deleteById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
203
204    /**
205     * 根据多个主键批量删除数据。
206     *
207     * @param ids 主键列表
208     * @return 受影响的行数
209     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext)
210     */
211    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteBatchByIds")
212    int deleteBatchByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
213
214    /**
215     * 根据多个主键批量删除数据。
216     *
217     * @param ids  主键列表
218     * @param size 切分大小
219     * @return 受影响的行数
220     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext)
221     */
222    default int deleteBatchByIds(List<? extends Serializable> ids, int size) {
223        if (size <= 0) {
224            size = DEFAULT_BATCH_SIZE;
225        }
226        int sum = 0;
227        int entitiesSize = ids.size();
228        int maxIndex = entitiesSize / size + (entitiesSize % size == 0 ? 0 : 1);
229        for (int i = 0; i < maxIndex; i++) {
230            List<? extends Serializable> list = ids.subList(i * size, Math.min(i * size + size, entitiesSize));
231            sum += deleteBatchByIds(list);
232        }
233        return sum;
234    }
235
236    /**
237     * 根据 Map 构建的条件来删除数据。
238     *
239     * @param whereConditions 条件
240     * @return 受影响的行数
241     */
242    default int deleteByMap(Map<String, Object> whereConditions) {
243        FlexAssert.notEmpty(whereConditions, "deleteByMap is not allow empty map.");
244        return deleteByQuery(QueryWrapper.create().where(whereConditions));
245    }
246
247    /**
248     * 根据查询条件来删除数据。
249     *
250     * @param whereConditions 条件
251     * @return 受影响的行数
252     */
253    default int deleteByCondition(QueryCondition whereConditions) {
254        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
255        return deleteByQuery(QueryWrapper.create().where(whereConditions));
256    }
257
258    /**
259     * 根据查询条件来删除数据。
260     *
261     * @param queryWrapper 条件
262     * @return 受影响的行数
263     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteByQuery(Map, ProviderContext)
264     */
265    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteByQuery")
266    int deleteByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
267
268    // === 改(update) ===
269
270    /**
271     * 根据主键来更新数据,若实体类属性数据为 {@code null},该属性不会新到数据库。
272     *
273     * @param entity 数据内容,必须包含有主键
274     * @return 受影响的行数
275     */
276    default int update(T entity) {
277        return update(entity, true);
278    }
279
280    /**
281     * 根据主键来更新数据到数据库。
282     *
283     * @param entity      数据内容,必须包含有主键
284     * @param ignoreNulls 是否忽略空内容字段
285     * @return 受影响的行数
286     * @see com.mybatisflex.core.provider.EntitySqlProvider#update(Map, ProviderContext)
287     */
288    @UpdateProvider(type = EntitySqlProvider.class, method = "update")
289    int update(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
290
291    /**
292     * 根据 Map 构建的条件来更新数据。
293     *
294     * @param entity          实体类
295     * @param whereConditions 条件
296     * @return 受影响的行数
297     */
298    default int updateByMap(T entity, Map<String, Object> whereConditions) {
299        FlexAssert.notEmpty(whereConditions, "updateByMap is not allow empty map.");
300        return updateByQuery(entity, QueryWrapper.create().where(whereConditions));
301    }
302
303    /**
304     * 根据 Map 构建的条件来更新数据。
305     *
306     * @param entity          实体类
307     * @param ignoreNulls     是否忽略 {@code null} 数据
308     * @param whereConditions 条件
309     * @return 受影响的行数
310     */
311    default int updateByMap(T entity, boolean ignoreNulls, Map<String, Object> whereConditions) {
312        FlexAssert.notEmpty(whereConditions, "updateByMap is not allow empty map.");
313        return updateByQuery(entity, ignoreNulls, QueryWrapper.create().where(whereConditions));
314    }
315
316    /**
317     * 根据查询条件来更新数据。
318     *
319     * @param entity          实体类
320     * @param whereConditions 条件
321     * @return 受影响的行数
322     */
323    default int updateByCondition(T entity, QueryCondition whereConditions) {
324        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
325        return updateByQuery(entity, QueryWrapper.create().where(whereConditions));
326    }
327
328    /**
329     * 根据查询条件来更新数据。
330     *
331     * @param entity          实体类
332     * @param ignoreNulls     是否忽略 {@code null} 数据
333     * @param whereConditions 条件
334     * @return 受影响的行数
335     */
336    default int updateByCondition(T entity, boolean ignoreNulls, QueryCondition whereConditions) {
337        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
338        return updateByQuery(entity, ignoreNulls, QueryWrapper.create().where(whereConditions));
339    }
340
341    /**
342     * 根据查询条件来更新数据。
343     *
344     * @param entity       实体类
345     * @param queryWrapper 条件
346     * @return 受影响的行数
347     */
348    default int updateByQuery(T entity, QueryWrapper queryWrapper) {
349        return updateByQuery(entity, true, queryWrapper);
350    }
351
352    /**
353     * 根据查询条件来更新数据。
354     *
355     * @param entity       实体类
356     * @param ignoreNulls  是否忽略空值
357     * @param queryWrapper 条件
358     * @return 受影响的行数
359     * @see com.mybatisflex.core.provider.EntitySqlProvider#updateByQuery(Map, ProviderContext)
360     */
361    @UpdateProvider(type = EntitySqlProvider.class, method = "updateByQuery")
362    int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
363
364    /**
365     * 执行类似 {@code update table set field = field + 1 where ... } 的场景。
366     *
367     * @param fieldName    字段名
368     * @param value        值(大于等于 0 加,小于 0 减)
369     * @param queryWrapper 条件
370     * @return 受影响的行数
371     * @see EntitySqlProvider#updateNumberAddByQuery(Map, ProviderContext)
372     */
373    @UpdateProvider(type = EntitySqlProvider.class, method = "updateNumberAddByQuery")
374    int updateNumberAddByQuery(@Param(FlexConsts.FIELD_NAME) String fieldName, @Param(FlexConsts.VALUE) Number value, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
375
376    /**
377     * 执行类似 {@code update table set field = field + 1 where ... } 的场景。
378     *
379     * @param column       字段名
380     * @param value        值(大于等于 0 加,小于 0 减)
381     * @param queryWrapper 条件
382     * @return 受影响的行数
383     * @see EntitySqlProvider#updateNumberAddByQuery(Map, ProviderContext)
384     */
385    default int updateNumberAddByQuery(QueryColumn column, Number value, QueryWrapper queryWrapper) {
386        FlexAssert.notNull(value, "add value can not be null.");
387        return updateNumberAddByQuery(column.getName(), value, queryWrapper);
388    }
389
390    /**
391     * 执行类似 {@code update table set field = field + 1 where ... } 的场景。
392     *
393     * @param fn           字段名
394     * @param value        值(大于等于 0 加,小于 0 减)
395     * @param queryWrapper 条件
396     * @return 受影响的行数
397     * @see EntitySqlProvider#updateNumberAddByQuery(Map, ProviderContext)
398     */
399    default int updateNumberAddByQuery(LambdaGetter<T> fn, Number value, QueryWrapper queryWrapper) {
400        FlexAssert.notNull(value, "add value can not be null.");
401        TableInfo tableInfo = TableInfoFactory.ofMapperClass(ClassUtil.getUsefulClass(getClass()));
402        String column = tableInfo.getColumnByProperty(LambdaUtil.getFieldName(fn));
403        return updateNumberAddByQuery(column, value, queryWrapper);
404    }
405
406    // === 查(select) ===
407
408    /**
409     * 根据主键查询数据。
410     *
411     * @param id 主键
412     * @return 实体类数据
413     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectOneById(Map, ProviderContext)
414     */
415    @SelectProvider(type = EntitySqlProvider.class, method = "selectOneById")
416    T selectOneById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
417
418    /**
419     * 根据 Map 构建的条件来查询数据。
420     *
421     * @param whereConditions 条件
422     * @return 实体类数据
423     */
424    default T selectOneByMap(Map<String, Object> whereConditions) {
425        FlexAssert.notEmpty(whereConditions, "whereConditions map can not be null or empty.");
426        return selectOneByQuery(QueryWrapper.create().where(whereConditions).limit(1));
427    }
428
429    /**
430     * 根据查询条件查询数据。
431     *
432     * @param whereConditions 条件
433     * @return 实体类数据
434     */
435    default T selectOneByCondition(QueryCondition whereConditions) {
436        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
437        return selectOneByQuery(QueryWrapper.create().where(whereConditions).limit(1));
438    }
439
440    /**
441     * 根据查询条件来查询 1 条数据。
442     *
443     * @param queryWrapper 条件
444     * @return 实体类数据
445     */
446    default T selectOneByQuery(QueryWrapper queryWrapper) {
447        return MapperUtil.getSelectOneResult(selectListByQuery(queryWrapper));
448    }
449
450    /**
451     * 根据查询条件来查询 1 条数据。
452     *
453     * @param queryWrapper 条件
454     * @param asType       接收数据类型
455     * @return 实体类数据
456     */
457    default <R> R selectOneByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
458        return MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType));
459    }
460
461    /**
462     * 根据 Map 构建的条件来查询 1 条数据。
463     *
464     * @param whereConditions 条件
465     * @return 实体类数据
466     */
467    default T selectOneWithRelationsByMap(Map<String, Object> whereConditions) {
468        FlexAssert.notEmpty(whereConditions, "whereConditions map can not be null or empty.");
469        return selectOneWithRelationsByQuery(QueryWrapper.create().where(whereConditions).limit(1));
470    }
471
472    /**
473     * 根据查询条件查询 1 条数据。
474     *
475     * @param whereConditions 条件
476     * @return 实体类数据
477     */
478    default T selectOneWithRelationsByCondition(QueryCondition whereConditions) {
479        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
480        return selectOneWithRelationsByQuery(QueryWrapper.create().where(whereConditions).limit(1));
481    }
482
483    /**
484     * 根据查询条件来查询 1 条数据。
485     *
486     * @param queryWrapper 条件
487     * @return 实体类数据
488     */
489    default T selectOneWithRelationsByQuery(QueryWrapper queryWrapper) {
490        return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQuery(queryWrapper)));
491    }
492
493    /**
494     * 根据查询条件来查询 1 条数据。
495     *
496     * @param queryWrapper 条件
497     * @param asType       接收数据类型
498     * @return 实体类数据
499     */
500    default <R> R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
501        return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType)));
502    }
503
504    /**
505     * 根据多个主键来查询多条数据。
506     *
507     * @param ids 主键列表
508     * @return 数据列表
509     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByIds(Map, ProviderContext)
510     */
511    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByIds")
512    List<T> selectListByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
513
514    /**
515     * 根据 Map 来构建查询条件,查询多条数据。
516     *
517     * @param whereConditions 条件
518     * @return 数据列表
519     */
520    default List<T> selectListByMap(Map<String, Object> whereConditions) {
521        FlexAssert.notEmpty(whereConditions, "whereConditions map can not be null or empty.");
522        return selectListByQuery(QueryWrapper.create().where(whereConditions));
523    }
524
525    /**
526     * 根据 Map 来构建查询条件,查询多条数据。
527     *
528     * @param whereConditions 条件
529     * @param count           数据量
530     * @return 数据列表
531     */
532    default List<T> selectListByMap(Map<String, Object> whereConditions, int count) {
533        FlexAssert.notEmpty(whereConditions, "whereConditions map can not be null or empty.");
534        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
535    }
536
537    /**
538     * 根据查询条件查询多条数据。
539     *
540     * @param whereConditions 条件
541     * @return 数据列表
542     */
543    default List<T> selectListByCondition(QueryCondition whereConditions) {
544        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
545        return selectListByQuery(QueryWrapper.create().where(whereConditions));
546    }
547
548    /**
549     * 根据查询条件查询多条数据。
550     *
551     * @param whereConditions 条件
552     * @param count           数据量
553     * @return 数据列表
554     */
555    default List<T> selectListByCondition(QueryCondition whereConditions, int count) {
556        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
557        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
558    }
559
560    /**
561     * 根据查询条件查询数据列表。
562     *
563     * @param queryWrapper 条件
564     * @return 数据列表
565     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByQuery(Map, ProviderContext)
566     */
567    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
568    List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
569
570    /**
571     * 根据查询条件查询数据列表。
572     *
573     * @param queryWrapper 条件
574     * @param consumers    字段查询
575     * @return 数据列表
576     */
577    default List<T> selectListByQuery(QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
578        List<T> list = selectListByQuery(queryWrapper);
579        if (list == null || list.isEmpty()) {
580            return Collections.emptyList();
581        }
582        MapperUtil.queryFields(this, list, consumers);
583        return list;
584    }
585
586    /**
587     * 根据查询条件查询游标数据,该方法必须在事务中才能正常使用,非事务下无法获取数据。
588     *
589     * @param queryWrapper 条件
590     * @return 游标数据
591     */
592    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
593    Cursor<T> selectCursorByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
594
595    /**
596     * 根据查询条件查询 Row 数据。
597     *
598     * @param queryWrapper 条件
599     * @return 行数据
600     */
601    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
602    List<Row> selectRowsByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
603
604    /**
605     * 根据查询条件查询数据列表,要求返回的数据为 asType。这种场景一般用在 left join 时,
606     * 有多出了实体类本身的字段内容,可以转换为 dto、vo 等场景。
607     *
608     * @param queryWrapper 条件
609     * @param asType       接收数据类型
610     * @return 数据列表
611     */
612    default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
613        if (Number.class.isAssignableFrom(asType)
614            || String.class == asType) {
615            return selectObjectListByQueryAs(queryWrapper, asType);
616        }
617
618        if (Map.class.isAssignableFrom(asType)) {
619            return (List<R>) selectRowsByQuery(queryWrapper);
620        }
621
622        try {
623            MappedStatementTypes.setCurrentType(asType);
624            return (List<R>) selectListByQuery(queryWrapper);
625        } finally {
626            MappedStatementTypes.clear();
627        }
628    }
629
630    /**
631     * 根据查询条件查询数据列表,要求返回的数据为 asType 类型。
632     *
633     * @param queryWrapper 条件
634     * @param asType       接收的数据类型
635     * @param consumers    字段查询
636     * @return 数据列表
637     */
638    default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
639        List<R> list = selectListByQueryAs(queryWrapper, asType);
640        if (list == null || list.isEmpty()) {
641            return Collections.emptyList();
642        } else {
643            MapperUtil.queryFields(this, list, consumers);
644            return list;
645        }
646    }
647
648    /**
649     * 查询实体类及其 Relation 注解字段。
650     *
651     * @param queryWrapper 条件
652     */
653    default List<T> selectListWithRelationsByQuery(QueryWrapper queryWrapper) {
654        return MapperUtil.queryRelations(this, selectListByQuery(queryWrapper));
655    }
656
657    /**
658     * 查询实体类及其 Relation 注解字段。
659     *
660     * @param queryWrapper 条件
661     * @param asType       要求返回的数据类型
662     * @return 数据列表
663     */
664    default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
665        if (Number.class.isAssignableFrom(asType)
666            || String.class == asType) {
667            return selectObjectListByQueryAs(queryWrapper, asType);
668        }
669
670        if (Map.class.isAssignableFrom(asType)) {
671            return (List<R>) selectRowsByQuery(queryWrapper);
672        }
673
674        List<T> result;
675        try {
676            MappedStatementTypes.setCurrentType(asType);
677            result = selectListByQuery(queryWrapper);
678        } finally {
679            MappedStatementTypes.clear();
680        }
681        return MapperUtil.queryRelations(this, (List<R>) result);
682    }
683
684    /**
685     * 查询实体类及其 Relation 注解字段。
686     *
687     * @param queryWrapper 条件
688     * @param asType       返回的类型
689     * @param consumers    字段查询
690     * @return 数据列表
691     */
692    default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
693        List<R> list = selectListByQueryAs(queryWrapper, asType);
694        if (list == null || list.isEmpty()) {
695            return Collections.emptyList();
696        } else {
697            MapperUtil.queryRelations(this, list);
698            MapperUtil.queryFields(this, list, consumers);
699            return list;
700        }
701    }
702
703    /**
704     * 查询全部数据。
705     *
706     * @return 数据列表
707     */
708    default List<T> selectAll() {
709        return selectListByQuery(new QueryWrapper());
710    }
711
712    /**
713     * 查询全部数据,及其 Relation 字段内容。
714     *
715     * @return 数据列表
716     */
717    default List<T> selectAllWithRelations() {
718        return MapperUtil.queryRelations(this, selectListByQuery(new QueryWrapper()));
719    }
720
721    /**
722     * 查询第一列返回的数据,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
723     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
724     *
725     * @param queryWrapper 查询包装器
726     * @return 数据量
727     */
728    default Object selectObjectByQuery(QueryWrapper queryWrapper) {
729        return MapperUtil.getSelectOneResult(selectObjectListByQuery(queryWrapper));
730    }
731
732    /**
733     * 查询第一列返回的数据,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
734     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
735     *
736     * @param queryWrapper 查询包装器
737     * @param asType       转换成的数据类型
738     * @return 数据量
739     */
740    default <R> R selectObjectByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
741        return MapperUtil.getSelectOneResult(selectObjectListByQueryAs(queryWrapper, asType));
742    }
743
744    /**
745     * 查询第一列返回的数据集合,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
746     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
747     *
748     * @param queryWrapper 查询包装器
749     * @return 数据列表
750     * @see EntitySqlProvider#selectObjectByQuery(Map, ProviderContext)
751     */
752    @SelectProvider(type = EntitySqlProvider.class, method = "selectObjectByQuery")
753    List<Object> selectObjectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
754
755    /**
756     * 查询第一列返回的数据集合,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
757     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
758     *
759     * @param queryWrapper 查询包装器
760     * @param asType       转换成的数据类型
761     * @return 数据列表
762     */
763    default <R> List<R> selectObjectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
764        List<Object> queryResults = selectObjectListByQuery(queryWrapper);
765        if (queryResults == null || queryResults.isEmpty()) {
766            return Collections.emptyList();
767        }
768        List<R> results = new ArrayList<>(queryResults.size());
769        for (Object queryResult : queryResults) {
770            results.add((R) ConvertUtil.convert(queryResult, asType));
771        }
772        return results;
773    }
774
775    /**
776     * 查询数据量。
777     *
778     * @param queryWrapper 条件
779     * @return 数据量
780     */
781    default long selectCountByQuery(QueryWrapper queryWrapper) {
782        List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
783        try {
784            List<Object> objects;
785            if (CollectionUtil.isEmpty(selectColumns)) {
786                // 未设置 COUNT(...) 列,默认使用 COUNT(*) 查询
787                queryWrapper.select(count());
788                objects = selectObjectListByQuery(queryWrapper);
789            } else if (selectColumns.get(0) instanceof FunctionQueryColumn) {
790                // COUNT 函数必须在第一列
791                if (!FuncName.COUNT.equalsIgnoreCase(
792                    ((FunctionQueryColumn) selectColumns.get(0)).getFnName()
793                )) {
794                    // 第一个查询列不是 COUNT 函数,使用 COUNT(*) 替换所有的查询列
795                    queryWrapper.select(count());
796                }
797                // 第一个查询列是 COUNT 函数,可以使用 COUNT(1)、COUNT(列名) 代替默认的 COUNT(*)
798                objects = selectObjectListByQuery(queryWrapper);
799            } else {
800                // 查询列中的第一列不是 COUNT 函数
801                if (MapperUtil.hasDistinct(selectColumns)) {
802                    // 查询列中包含 DISTINCT 去重
803                    // 使用子查询 SELECT COUNT(*) FROM (SELECT DISTINCT ...) AS `t`
804                    objects = selectObjectListByQuery(MapperUtil.rawCountQueryWrapper(queryWrapper));
805                } else {
806                    // 使用 COUNT(*) 替换所有的查询列
807                    queryWrapper.select(count());
808                    objects = selectObjectListByQuery(queryWrapper);
809                }
810            }
811            return MapperUtil.getLongNumber(objects);
812        } finally {
813            //fixed https://github.com/mybatis-flex/mybatis-flex/issues/49
814            CPI.setSelectColumns(queryWrapper, selectColumns);
815        }
816    }
817
818    /**
819     * 根据条件查询数据总量。
820     *
821     * @param whereConditions 条件
822     * @return 数据量
823     */
824    default long selectCountByCondition(QueryCondition whereConditions) {
825        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
826        return selectCountByQuery(QueryWrapper.create().where(whereConditions));
827    }
828
829    /**
830     * 分页查询。
831     *
832     * @param pageNumber   当前页码
833     * @param pageSize     每页的数据量
834     * @param queryWrapper 条件
835     * @return 分页数据
836     */
837    default Page<T> paginate(int pageNumber, int pageSize, QueryWrapper queryWrapper) {
838        Page<T> page = new Page<>(pageNumber, pageSize);
839        return paginate(page, queryWrapper);
840    }
841
842    /**
843     * 分页查询,及其 Relation 字段内容。
844     *
845     * @param pageNumber   当前页码
846     * @param pageSize     每页的数据量
847     * @param queryWrapper 条件
848     * @return 分页数据
849     */
850    default Page<T> paginateWithRelations(int pageNumber, int pageSize, QueryWrapper queryWrapper) {
851        Page<T> page = new Page<>(pageNumber, pageSize);
852        return paginateWithRelations(page, queryWrapper);
853    }
854
855    /**
856     * 分页查询。
857     *
858     * @param pageNumber      当前页码
859     * @param pageSize        每页的数据量
860     * @param whereConditions 条件
861     * @return 分页数据
862     */
863    default Page<T> paginate(int pageNumber, int pageSize, QueryCondition whereConditions) {
864        Page<T> page = new Page<>(pageNumber, pageSize);
865        return paginate(page, new QueryWrapper().where(whereConditions));
866    }
867
868    /**
869     * 分页查询,及其 Relation 字段内容。
870     *
871     * @param pageNumber      当前页码
872     * @param pageSize        每页的数据量
873     * @param whereConditions 条件
874     * @return 分页数据
875     */
876    default Page<T> paginateWithRelations(int pageNumber, int pageSize, QueryCondition whereConditions) {
877        Page<T> page = new Page<>(pageNumber, pageSize);
878        return paginateWithRelations(page, new QueryWrapper().where(whereConditions));
879    }
880
881    /**
882     * 分页查询。
883     *
884     * @param pageNumber   当前页码
885     * @param pageSize     每页的数据量
886     * @param totalRow     数据总量
887     * @param queryWrapper 条件
888     * @return 分页数据
889     */
890    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper) {
891        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
892        return paginate(page, queryWrapper);
893    }
894
895    /**
896     * 分页查询,及其 Relation 字段内容。
897     *
898     * @param pageNumber   当前页码
899     * @param pageSize     每页的数据量
900     * @param totalRow     数据总量
901     * @param queryWrapper 条件
902     * @return 分页数据
903     */
904    default Page<T> paginateWithRelations(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper) {
905        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
906        return paginateWithRelations(page, queryWrapper);
907    }
908
909    /**
910     * 分页查询。
911     *
912     * @param pageNumber      当前页码
913     * @param pageSize        每页的数据量
914     * @param totalRow        数据总量
915     * @param whereConditions 条件
916     * @return 分页数据
917     */
918    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryCondition whereConditions) {
919        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
920        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
921        return paginate(page, new QueryWrapper().where(whereConditions));
922    }
923
924    /**
925     * 分页查询,及其 Relation 字段内容。
926     *
927     * @param pageNumber      当前页码
928     * @param pageSize        每页的数据量
929     * @param totalRow        数据总量
930     * @param whereConditions 条件
931     * @return 分页数据
932     */
933    default Page<T> paginateWithRelations(int pageNumber, int pageSize, int totalRow, QueryCondition whereConditions) {
934        FlexAssert.notNull(whereConditions, "whereConditions can not be null.");
935        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
936        return paginateWithRelations(page, new QueryWrapper().where(whereConditions));
937    }
938
939    /**
940     * 分页查询。
941     *
942     * @param page         包含了页码、每页的数据量,可能包含数据总量
943     * @param queryWrapper 条件
944     * @return page 数据
945     */
946    default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper) {
947        return paginateAs(page, queryWrapper, null);
948    }
949
950    /**
951     * 分页查询。
952     *
953     * @param page         包含了页码、每页的数据量,可能包含数据总量
954     * @param queryWrapper 条件
955     * @param consumers    字段查询
956     * @return page 数据
957     */
958    default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
959        return paginateAs(page, queryWrapper, null, consumers);
960    }
961
962    /**
963     * 分页查询,及其 Relation 字段内容。
964     *
965     * @param page         包含了页码、每页的数据量,可能包含数据总量
966     * @param queryWrapper 条件
967     * @return 分页数据
968     */
969    default Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper) {
970        return paginateWithRelationsAs(page, queryWrapper, null);
971    }
972
973    /**
974     * 分页查询,及其 Relation 字段内容。
975     *
976     * @param page         包含了页码、每页的数据量,可能包含数据总量
977     * @param queryWrapper 条件
978     * @param consumers    字段查询
979     * @return 分页数据
980     */
981    default Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
982        return paginateWithRelationsAs(page, queryWrapper, null, consumers);
983    }
984
985    /**
986     * 分页查询。
987     *
988     * @param pageNumber   当前页码
989     * @param pageSize     每页的数据量
990     * @param queryWrapper 条件
991     * @param asType       接收数据类型
992     * @return 分页数据
993     */
994    default <R> Page<R> paginateAs(int pageNumber, int pageSize, QueryWrapper queryWrapper, Class<R> asType) {
995        Page<R> page = new Page<>(pageNumber, pageSize);
996        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
997    }
998
999    /**
1000     * 分页查询。
1001     *
1002     * @param pageNumber   当前页码
1003     * @param pageSize     每页的数据量
1004     * @param totalRow     数据总量
1005     * @param queryWrapper 条件
1006     * @param asType       接收数据类型
1007     * @return 分页数据
1008     */
1009    default <R> Page<R> paginateAs(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper, Class<R> asType) {
1010        Page<R> page = new Page<>(pageNumber, pageSize, totalRow);
1011        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
1012    }
1013
1014    /**
1015     * 分页查询。
1016     *
1017     * @param page         包含了页码、每页的数据量,可能包含数据总量
1018     * @param queryWrapper 条件
1019     * @param asType       接收数据类型
1020     * @return 分页数据
1021     */
1022    default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType) {
1023        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
1024    }
1025
1026    /**
1027     * 分页查询。
1028     *
1029     * @param page         包含了页码、每页的数据量,可能包含数据总量
1030     * @param queryWrapper 条件
1031     * @param asType       接收数据类型
1032     * @param consumers    字段查询
1033     * @return 分页数据
1034     */
1035    default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
1036        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false, consumers);
1037    }
1038
1039    /**
1040     * 分页查询,及其 Relation 字段内容。
1041     *
1042     * @param pageNumber   当前页码
1043     * @param pageSize     每页的数据量
1044     * @param queryWrapper 条件
1045     * @param asType       接收数据类型
1046     * @return 分页数据
1047     */
1048    default <R> Page<R> paginateWithRelationsAs(int pageNumber, int pageSize, QueryWrapper queryWrapper, Class<R> asType) {
1049        Page<R> page = new Page<>(pageNumber, pageSize);
1050        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1051    }
1052
1053    /**
1054     * 分页查询,及其 Relation 字段内容。
1055     *
1056     * @param pageNumber   当前页码
1057     * @param pageSize     每页的数据量
1058     * @param totalRow     数据总量
1059     * @param queryWrapper 条件
1060     * @param asType       接收数据类型
1061     * @return 分页数据
1062     */
1063    default <R> Page<R> paginateWithRelationsAs(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper, Class<R> asType) {
1064        Page<R> page = new Page<>(pageNumber, pageSize, totalRow);
1065        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1066    }
1067
1068    /**
1069     * 分页查询,及其 Relation 字段内容。
1070     *
1071     * @param page         包含了页码、每页的数据量,可能包含数据总量
1072     * @param queryWrapper 条件
1073     * @param asType       接收数据类型
1074     * @return 分页数据
1075     */
1076    default <R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType) {
1077        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1078    }
1079
1080    /**
1081     * 分页查询,及其 Relation 字段内容。
1082     *
1083     * @param page         包含了页码、每页的数据量,可能包含数据总量
1084     * @param queryWrapper 条件
1085     * @param asType       接收数据类型
1086     * @param consumers    字段查询
1087     * @return 分页数据
1088     */
1089    default <R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
1090        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true, consumers);
1091    }
1092
1093}