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