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