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