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