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