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        queryWrapper.limit(1);
437        return MapperUtil.getSelectOneResult(selectListByQuery(queryWrapper));
438    }
439
440    /**
441     * 根据查询条件来查询 1 条数据。
442     *
443     * @param queryWrapper 条件
444     * @param asType       接收数据类型
445     * @return 实体类数据
446     */
447    default <R> R selectOneByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
448        return MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType));
449    }
450
451    /**
452     * 根据 Map 构建的条件来查询 1 条数据。
453     *
454     * @param whereConditions 条件
455     * @return 实体类数据
456     */
457    default T selectOneWithRelationsByMap(Map<String, Object> whereConditions) {
458        FlexAssert.notEmpty(whereConditions, "whereConditions");
459        return selectOneWithRelationsByQuery(QueryWrapper.create().where(whereConditions).limit(1L));
460    }
461
462    /**
463     * 根据查询条件查询 1 条数据。
464     *
465     * @param whereConditions 条件
466     * @return 实体类数据
467     */
468    default T selectOneWithRelationsByCondition(QueryCondition whereConditions) {
469        FlexAssert.notNull(whereConditions, "whereConditions");
470        return selectOneWithRelationsByQuery(QueryWrapper.create().where(whereConditions).limit(1L));
471    }
472
473    /**
474     * 根据查询条件来查询 1 条数据。
475     *
476     * @param queryWrapper 条件
477     * @return 实体类数据
478     */
479    default T selectOneWithRelationsByQuery(QueryWrapper queryWrapper) {
480        return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQuery(queryWrapper)));
481    }
482
483    /**
484     * 根据主表主键来查询 1 条数据。
485     *
486     * @param id 主表主键
487     * @return 实体类数据
488     */
489    default T selectOneWithRelationsById(Serializable id) {
490        return MapperUtil.queryRelations(this, selectOneById(id));
491    }
492
493    /**
494     * 根据主表主键来查询 1 条数据。
495     *
496     * @param id     表主键
497     * @param asType 接收数据类型
498     * @return 实体类数据
499     */
500    default <R> R selectOneWithRelationsByIdAs(Serializable id, Class<R> asType) {
501        try {
502            MappedStatementTypes.setCurrentType(asType);
503            return (R) selectOneWithRelationsById(id);
504        } finally {
505            MappedStatementTypes.clear();
506        }
507    }
508
509    /**
510     * 根据查询条件来查询 1 条数据。
511     *
512     * @param queryWrapper 条件
513     * @param asType       接收数据类型
514     * @return 实体类数据
515     */
516    default <R> R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
517        return MapperUtil.queryRelations(this, MapperUtil.getSelectOneResult(selectListByQueryAs(queryWrapper, asType)));
518    }
519
520    /**
521     * 根据多个主键来查询多条数据。
522     *
523     * @param ids 主键列表
524     * @return 数据列表
525     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByIds(Map, ProviderContext)
526     */
527    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByIds")
528    List<T> selectListByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
529
530    /**
531     * 根据 Map 来构建查询条件,查询多条数据。
532     *
533     * @param whereConditions 条件
534     * @return 数据列表
535     */
536    default List<T> selectListByMap(Map<String, Object> whereConditions) {
537        FlexAssert.notEmpty(whereConditions, "whereConditions");
538        return selectListByQuery(QueryWrapper.create().where(whereConditions));
539    }
540
541    /**
542     * 根据 Map 来构建查询条件,查询多条数据。
543     *
544     * @param whereConditions 条件
545     * @param count           数据量
546     * @return 数据列表
547     */
548    default List<T> selectListByMap(Map<String, Object> whereConditions, Long count) {
549        FlexAssert.notEmpty(whereConditions, "whereConditions");
550        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
551    }
552
553    /**
554     * 根据查询条件查询多条数据。
555     *
556     * @param whereConditions 条件
557     * @return 数据列表
558     */
559    default List<T> selectListByCondition(QueryCondition whereConditions) {
560        FlexAssert.notNull(whereConditions, "whereConditions");
561        return selectListByQuery(QueryWrapper.create().where(whereConditions));
562    }
563
564    /**
565     * 根据查询条件查询多条数据。
566     *
567     * @param whereConditions 条件
568     * @param count           数据量
569     * @return 数据列表
570     */
571    default List<T> selectListByCondition(QueryCondition whereConditions, Long count) {
572        FlexAssert.notNull(whereConditions, "whereConditions");
573        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
574    }
575
576    /**
577     * 根据查询条件查询数据列表。
578     *
579     * @param queryWrapper 条件
580     * @return 数据列表
581     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByQuery(Map, ProviderContext)
582     */
583    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
584    List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
585
586    /**
587     * 根据查询条件查询数据列表。
588     *
589     * @param queryWrapper 条件
590     * @param consumers    字段查询
591     * @return 数据列表
592     */
593    default List<T> selectListByQuery(QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
594        List<T> list = selectListByQuery(queryWrapper);
595        if (list == null || list.isEmpty()) {
596            return Collections.emptyList();
597        }
598        MapperUtil.queryFields(this, list, consumers);
599        return list;
600    }
601
602    /**
603     * 根据查询条件查询游标数据,该方法必须在事务中才能正常使用,非事务下无法获取数据。
604     *
605     * @param queryWrapper 条件
606     * @return 游标数据
607     */
608    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
609    Cursor<T> selectCursorByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
610
611    /**
612     * 根据查询条件查询 Row 数据。
613     *
614     * @param queryWrapper 条件
615     * @return 行数据
616     */
617    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
618    List<Row> selectRowsByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
619
620    /**
621     * 根据查询条件查询数据列表,要求返回的数据为 asType。这种场景一般用在 left join 时,
622     * 有多出了实体类本身的字段内容,可以转换为 dto、vo 等场景。
623     *
624     * @param queryWrapper 条件
625     * @param asType       接收数据类型
626     * @return 数据列表
627     */
628    default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
629        if (Number.class.isAssignableFrom(asType)
630            || String.class == asType) {
631            return selectObjectListByQueryAs(queryWrapper, asType);
632        }
633
634        if (Map.class.isAssignableFrom(asType)) {
635            return (List<R>) selectRowsByQuery(queryWrapper);
636        }
637
638        try {
639            MappedStatementTypes.setCurrentType(asType);
640            return (List<R>) selectListByQuery(queryWrapper);
641        } finally {
642            MappedStatementTypes.clear();
643        }
644    }
645
646    /**
647     * 根据查询条件查询数据列表,要求返回的数据为 asType 类型。
648     *
649     * @param queryWrapper 条件
650     * @param asType       接收的数据类型
651     * @param consumers    字段查询
652     * @return 数据列表
653     */
654    default <R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
655        List<R> list = selectListByQueryAs(queryWrapper, asType);
656        if (list == null || list.isEmpty()) {
657            return Collections.emptyList();
658        } else {
659            MapperUtil.queryFields(this, list, consumers);
660            return list;
661        }
662    }
663
664    /**
665     * 查询实体类及其 Relation 注解字段。
666     *
667     * @param queryWrapper 条件
668     */
669    default List<T> selectListWithRelationsByQuery(QueryWrapper queryWrapper) {
670        return MapperUtil.queryRelations(this, selectListByQuery(queryWrapper));
671    }
672
673    /**
674     * 查询实体类及其 Relation 注解字段。
675     *
676     * @param queryWrapper 条件
677     * @param asType       要求返回的数据类型
678     * @return 数据列表
679     */
680    default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
681        if (Number.class.isAssignableFrom(asType)
682            || String.class == asType) {
683            return selectObjectListByQueryAs(queryWrapper, asType);
684        }
685
686        if (Map.class.isAssignableFrom(asType)) {
687            return (List<R>) selectRowsByQuery(queryWrapper);
688        }
689
690        List<T> result;
691        try {
692            MappedStatementTypes.setCurrentType(asType);
693            result = selectListByQuery(queryWrapper);
694        } finally {
695            MappedStatementTypes.clear();
696        }
697        return MapperUtil.queryRelations(this, (List<R>) result);
698    }
699
700    /**
701     * 查询实体类及其 Relation 注解字段。
702     *
703     * @param queryWrapper 条件
704     * @param asType       返回的类型
705     * @param consumers    字段查询
706     * @return 数据列表
707     */
708    default <R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
709        List<R> list = selectListByQueryAs(queryWrapper, asType);
710        if (list == null || list.isEmpty()) {
711            return Collections.emptyList();
712        } else {
713            MapperUtil.queryRelations(this, list);
714            MapperUtil.queryFields(this, list, consumers);
715            return list;
716        }
717    }
718
719    /**
720     * 查询全部数据。
721     *
722     * @return 数据列表
723     */
724    default List<T> selectAll() {
725        return selectListByQuery(new QueryWrapper());
726    }
727
728    /**
729     * 查询全部数据,及其 Relation 字段内容。
730     *
731     * @return 数据列表
732     */
733    default List<T> selectAllWithRelations() {
734        return MapperUtil.queryRelations(this, selectListByQuery(new QueryWrapper()));
735    }
736
737    /**
738     * 查询第一列返回的数据,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
739     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
740     *
741     * @param queryWrapper 查询包装器
742     * @return 数据量
743     */
744    default Object selectObjectByQuery(QueryWrapper queryWrapper) {
745        return MapperUtil.getSelectOneResult(selectObjectListByQuery(queryWrapper));
746    }
747
748    /**
749     * 查询第一列返回的数据,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
750     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
751     *
752     * @param queryWrapper 查询包装器
753     * @param asType       转换成的数据类型
754     * @return 数据量
755     */
756    default <R> R selectObjectByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
757        return MapperUtil.getSelectOneResult(selectObjectListByQueryAs(queryWrapper, asType));
758    }
759
760    /**
761     * 查询第一列返回的数据集合,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
762     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
763     *
764     * @param queryWrapper 查询包装器
765     * @return 数据列表
766     * @see EntitySqlProvider#selectObjectByQuery(Map, ProviderContext)
767     */
768    @SelectProvider(type = EntitySqlProvider.class, method = "selectObjectByQuery")
769    List<Object> selectObjectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
770
771    /**
772     * 查询第一列返回的数据集合,QueryWrapper 执行的结果应该只有 1 列,例如:<br>
773     * {@code QueryWrapper.create().select(ACCOUNT.id).where(...);}
774     *
775     * @param queryWrapper 查询包装器
776     * @param asType       转换成的数据类型
777     * @return 数据列表
778     */
779    default <R> List<R> selectObjectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType) {
780        List<Object> queryResults = selectObjectListByQuery(queryWrapper);
781        if (queryResults == null || queryResults.isEmpty()) {
782            return Collections.emptyList();
783        }
784        List<R> results = new ArrayList<>(queryResults.size());
785        for (Object queryResult : queryResults) {
786            results.add((R) ConvertUtil.convert(queryResult, asType));
787        }
788        return results;
789    }
790
791    /**
792     * 查询数据量。
793     *
794     * @param queryWrapper 条件
795     * @return 数据量
796     */
797    default long selectCountByQuery(QueryWrapper queryWrapper) {
798        List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
799        try {
800            List<Object> objects;
801            if (CollectionUtil.isEmpty(selectColumns)) {
802                // 未设置 COUNT(...) 列,默认使用 COUNT(*) 查询
803                queryWrapper.select(count());
804                objects = selectObjectListByQuery(queryWrapper);
805            } else if (selectColumns.get(0) instanceof FunctionQueryColumn) {
806                // COUNT 函数必须在第一列
807                if (!FuncName.COUNT.equalsIgnoreCase(
808                    ((FunctionQueryColumn) selectColumns.get(0)).getFnName()
809                )) {
810                    // 第一个查询列不是 COUNT 函数,使用 COUNT(*) 替换所有的查询列
811                    CPI.setSelectColumns(queryWrapper, Collections.singletonList(count()));
812                }
813                // 第一个查询列是 COUNT 函数,可以使用 COUNT(1)、COUNT(列名) 代替默认的 COUNT(*)
814                objects = selectObjectListByQuery(queryWrapper);
815            } else {
816                // 查询列中的第一列不是 COUNT 函数
817                if (MapperUtil.hasDistinct(selectColumns)) {
818                    // 查询列中包含 DISTINCT 去重
819                    // 使用子查询 SELECT COUNT(*) FROM (SELECT DISTINCT ...) AS `t`
820                    objects = selectObjectListByQuery(MapperUtil.rawCountQueryWrapper(queryWrapper));
821                } else {
822                    // 使用 COUNT(*) 替换所有的查询列
823                    CPI.setSelectColumns(queryWrapper, Collections.singletonList(count()));
824                    objects = selectObjectListByQuery(queryWrapper);
825                }
826            }
827            return MapperUtil.getLongNumber(objects);
828        } finally {
829            //fixed https://github.com/mybatis-flex/mybatis-flex/issues/49
830            CPI.setSelectColumns(queryWrapper, selectColumns);
831        }
832    }
833
834    /**
835     * 根据条件查询数据总量。
836     *
837     * @param whereConditions 条件
838     * @return 数据量
839     */
840    default long selectCountByCondition(QueryCondition whereConditions) {
841        FlexAssert.notNull(whereConditions, "whereConditions");
842        return selectCountByQuery(QueryWrapper.create().where(whereConditions));
843    }
844
845    /**
846     * 分页查询。
847     *
848     * @param pageNumber   当前页码
849     * @param pageSize     每页的数据量
850     * @param queryWrapper 条件
851     * @return 分页数据
852     */
853    default Page<T> paginate(Number pageNumber, Number pageSize, QueryWrapper queryWrapper) {
854        Page<T> page = new Page<>(pageNumber, pageSize);
855        return paginate(page, queryWrapper);
856    }
857
858    /**
859     * 分页查询,及其 Relation 字段内容。
860     *
861     * @param pageNumber   当前页码
862     * @param pageSize     每页的数据量
863     * @param queryWrapper 条件
864     * @return 分页数据
865     */
866    default Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryWrapper queryWrapper) {
867        Page<T> page = new Page<>(pageNumber, pageSize);
868        return paginateWithRelations(page, queryWrapper);
869    }
870
871    /**
872     * 分页查询。
873     *
874     * @param pageNumber      当前页码
875     * @param pageSize        每页的数据量
876     * @param whereConditions 条件
877     * @return 分页数据
878     */
879    default Page<T> paginate(Number pageNumber, Number pageSize, QueryCondition whereConditions) {
880        Page<T> page = new Page<>(pageNumber, pageSize);
881        return paginate(page, new QueryWrapper().where(whereConditions));
882    }
883
884    /**
885     * 分页查询,及其 Relation 字段内容。
886     *
887     * @param pageNumber      当前页码
888     * @param pageSize        每页的数据量
889     * @param whereConditions 条件
890     * @return 分页数据
891     */
892    default Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryCondition whereConditions) {
893        Page<T> page = new Page<>(pageNumber, pageSize);
894        return paginateWithRelations(page, new QueryWrapper().where(whereConditions));
895    }
896
897    /**
898     * 分页查询。
899     *
900     * @param pageNumber   当前页码
901     * @param pageSize     每页的数据量
902     * @param totalRow     数据总量
903     * @param queryWrapper 条件
904     * @return 分页数据
905     */
906    default Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper) {
907        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
908        return paginate(page, queryWrapper);
909    }
910
911    /**
912     * 分页查询,及其 Relation 字段内容。
913     *
914     * @param pageNumber   当前页码
915     * @param pageSize     每页的数据量
916     * @param totalRow     数据总量
917     * @param queryWrapper 条件
918     * @return 分页数据
919     */
920    default Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper) {
921        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
922        return paginateWithRelations(page, queryWrapper);
923    }
924
925    /**
926     * 分页查询。
927     *
928     * @param pageNumber      当前页码
929     * @param pageSize        每页的数据量
930     * @param totalRow        数据总量
931     * @param whereConditions 条件
932     * @return 分页数据
933     */
934    default Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions) {
935        FlexAssert.notNull(whereConditions, "whereConditions");
936        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
937        return paginate(page, new QueryWrapper().where(whereConditions));
938    }
939
940    /**
941     * 分页查询,及其 Relation 字段内容。
942     *
943     * @param pageNumber      当前页码
944     * @param pageSize        每页的数据量
945     * @param totalRow        数据总量
946     * @param whereConditions 条件
947     * @return 分页数据
948     */
949    default Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions) {
950        FlexAssert.notNull(whereConditions, "whereConditions");
951        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
952        return paginateWithRelations(page, new QueryWrapper().where(whereConditions));
953    }
954
955    /**
956     * 分页查询。
957     *
958     * @param page         包含了页码、每页的数据量,可能包含数据总量
959     * @param queryWrapper 条件
960     * @return page 数据
961     */
962    default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper) {
963        return paginateAs(page, queryWrapper, null);
964    }
965
966    /**
967     * 分页查询。
968     *
969     * @param page         包含了页码、每页的数据量,可能包含数据总量
970     * @param queryWrapper 条件
971     * @param consumers    字段查询
972     * @return page 数据
973     */
974    default Page<T> paginate(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
975        return paginateAs(page, queryWrapper, null, consumers);
976    }
977
978    /**
979     * 分页查询,及其 Relation 字段内容。
980     *
981     * @param page         包含了页码、每页的数据量,可能包含数据总量
982     * @param queryWrapper 条件
983     * @return 分页数据
984     */
985    default Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper) {
986        return paginateWithRelationsAs(page, queryWrapper, null);
987    }
988
989    /**
990     * 分页查询,及其 Relation 字段内容。
991     *
992     * @param page         包含了页码、每页的数据量,可能包含数据总量
993     * @param queryWrapper 条件
994     * @param consumers    字段查询
995     * @return 分页数据
996     */
997    default Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers) {
998        return paginateWithRelationsAs(page, queryWrapper, null, consumers);
999    }
1000
1001    /**
1002     * 分页查询。
1003     *
1004     * @param pageNumber   当前页码
1005     * @param pageSize     每页的数据量
1006     * @param queryWrapper 条件
1007     * @param asType       接收数据类型
1008     * @return 分页数据
1009     */
1010    default <R> Page<R> paginateAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType) {
1011        Page<R> page = new Page<>(pageNumber, pageSize);
1012        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
1013    }
1014
1015    /**
1016     * 分页查询。
1017     *
1018     * @param pageNumber   当前页码
1019     * @param pageSize     每页的数据量
1020     * @param totalRow     数据总量
1021     * @param queryWrapper 条件
1022     * @param asType       接收数据类型
1023     * @return 分页数据
1024     */
1025    default <R> Page<R> paginateAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType) {
1026        Page<R> page = new Page<>(pageNumber, pageSize, totalRow);
1027        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
1028    }
1029
1030    /**
1031     * 分页查询。
1032     *
1033     * @param page         包含了页码、每页的数据量,可能包含数据总量
1034     * @param queryWrapper 条件
1035     * @param asType       接收数据类型
1036     * @return 分页数据
1037     */
1038    default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType) {
1039        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false);
1040    }
1041
1042    /**
1043     * 分页查询。
1044     *
1045     * @param page         包含了页码、每页的数据量,可能包含数据总量
1046     * @param queryWrapper 条件
1047     * @param asType       接收数据类型
1048     * @param consumers    字段查询
1049     * @return 分页数据
1050     */
1051    default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
1052        return MapperUtil.doPaginate(this, page, queryWrapper, asType, false, consumers);
1053    }
1054
1055    /**
1056     * 分页查询,及其 Relation 字段内容。
1057     *
1058     * @param pageNumber   当前页码
1059     * @param pageSize     每页的数据量
1060     * @param queryWrapper 条件
1061     * @param asType       接收数据类型
1062     * @return 分页数据
1063     */
1064    default <R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType) {
1065        Page<R> page = new Page<>(pageNumber, pageSize);
1066        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1067    }
1068
1069    /**
1070     * 分页查询,及其 Relation 字段内容。
1071     *
1072     * @param pageNumber   当前页码
1073     * @param pageSize     每页的数据量
1074     * @param totalRow     数据总量
1075     * @param queryWrapper 条件
1076     * @param asType       接收数据类型
1077     * @return 分页数据
1078     */
1079    default <R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType) {
1080        Page<R> page = new Page<>(pageNumber, pageSize, totalRow);
1081        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1082    }
1083
1084    /**
1085     * 分页查询,及其 Relation 字段内容。
1086     *
1087     * @param page         包含了页码、每页的数据量,可能包含数据总量
1088     * @param queryWrapper 条件
1089     * @param asType       接收数据类型
1090     * @return 分页数据
1091     */
1092    default <R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType) {
1093        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true);
1094    }
1095
1096    /**
1097     * 分页查询,及其 Relation 字段内容。
1098     *
1099     * @param page         包含了页码、每页的数据量,可能包含数据总量
1100     * @param queryWrapper 条件
1101     * @param asType       接收数据类型
1102     * @param consumers    字段查询
1103     * @return 分页数据
1104     */
1105    default <R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
1106        return MapperUtil.doPaginate(this, page, queryWrapper, asType, true, consumers);
1107    }
1108
1109
1110    default <E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper) {
1111        return xmlPaginate(dataSelectId, dataSelectId + "_COUNT", page, queryWrapper, null);
1112    }
1113
1114    default <E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, Map<String, Object> otherParams) {
1115        return xmlPaginate(dataSelectId, dataSelectId + "_COUNT", page, null, otherParams);
1116    }
1117
1118    default <E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams) {
1119        return xmlPaginate(dataSelectId, dataSelectId + "_COUNT", page, queryWrapper, otherParams);
1120    }
1121
1122    default <E> Page<E> xmlPaginate(String dataSelectId, String countSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams) {
1123        SqlSessionFactory sqlSessionFactory = FlexGlobalConfig.getDefaultConfig().getSqlSessionFactory();
1124        ExecutorType executorType = FlexGlobalConfig.getDefaultConfig().getConfiguration().getDefaultExecutorType();
1125        String mapperClassName = ClassUtil.getUsefulClass(this.getClass()).getName();
1126
1127        Map<String, Object> preparedParams = MapperUtil.preparedParams(page, queryWrapper, otherParams);
1128        if (!dataSelectId.contains(".")) {
1129            dataSelectId = mapperClassName + "." + dataSelectId;
1130        }
1131
1132        try (SqlSession sqlSession = sqlSessionFactory.openSession(executorType, false)) {
1133            if (page.getTotalRow() < 0) {
1134                if (!countSelectId.contains(".")) {
1135                    countSelectId = mapperClassName + "." + countSelectId;
1136                }
1137                Number number = sqlSession.selectOne(countSelectId, preparedParams);
1138                page.setTotalRow(number == null ? Page.INIT_VALUE : number.longValue());
1139            }
1140
1141            if (page.hasRecords()) {
1142                List<E> entities = sqlSession.selectList(dataSelectId, preparedParams);
1143                page.setRecords(entities);
1144            }
1145        }
1146        return page;
1147    }
1148
1149}