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