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