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