001/**
002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package com.mybatisflex.core;
017
018import com.mybatisflex.core.exception.FlexExceptions;
019import com.mybatisflex.core.paginate.Page;
020import com.mybatisflex.core.provider.EntitySqlProvider;
021import com.mybatisflex.core.query.QueryColumn;
022import com.mybatisflex.core.query.QueryCondition;
023import com.mybatisflex.core.query.QueryWrapper;
024import com.mybatisflex.core.query.CPI;
025import com.mybatisflex.core.table.TableInfo;
026import com.mybatisflex.core.table.TableInfoFactory;
027import com.mybatisflex.core.util.ObjectUtil;
028import org.apache.ibatis.annotations.*;
029import org.apache.ibatis.builder.annotation.ProviderContext;
030
031import java.io.Serializable;
032import java.util.Collection;
033import java.util.List;
034import java.util.Map;
035
036public interface BaseMapper<T> {
037
038    /**
039     * 插入 entity 数据
040     *
041     * @param entity 实体类
042     * @return 返回影响的行数
043     * @see com.mybatisflex.core.provider.EntitySqlProvider#insert(Map, ProviderContext)
044     */
045    @InsertProvider(type = EntitySqlProvider.class, method = "insert")
046    int insert(@Param(FlexConsts.ENTITY) T entity);
047
048
049    /**
050     * 批量插入 entity 数据,只会根据第一条数据来构建插入的字段内容
051     *
052     * @param entities 插入的数据列表
053     * @return 返回影响的行数
054     * @see com.mybatisflex.core.provider.EntitySqlProvider#insertBatch(Map, ProviderContext)
055     * @see com.mybatisflex.core.FlexConsts#METHOD_INSERT_BATCH
056     */
057    @InsertProvider(type = EntitySqlProvider.class, method = FlexConsts.METHOD_INSERT_BATCH)
058    int insertBatch(@Param(FlexConsts.ENTITIES) List<T> entities);
059
060
061    /**
062     * 新增 或者 更新,若主键有值,则更新,若没有主键值,则插入
063     *
064     * @param entity 实体类
065     * @return 返回影响的行数
066     */
067    default int insertOrUpdate(T entity) {
068        TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass());
069        Object[] pkArgs = tableInfo.buildPkSqlArgs(entity);
070        if (pkArgs.length == 0 || pkArgs[0] == null) {
071            return insert(entity);
072        } else {
073            return update(entity);
074        }
075    }
076
077    /**
078     * 根据 id 删除数据
079     * 如果是多个主键的情况下,需要传入数组 new Object[]{100,101}
080     *
081     * @param id 主键数据
082     * @return 返回影响的行数
083     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteById(Map, ProviderContext)
084     */
085    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteById")
086    int deleteById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
087
088
089    /**
090     * 根据多个 id 批量删除数据
091     *
092     * @param ids ids 列表
093     * @return 返回影响的行数
094     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext)
095     */
096    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteBatchByIds")
097    int deleteBatchByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
098
099
100    /**
101     * 根据 map 构建的条件来删除数据
102     *
103     * @param whereConditions 条件
104     * @return 返回影响的行数
105     */
106    default int deleteByMap(Map<String, Object> whereConditions) {
107        if (ObjectUtil.areNull(whereConditions) || whereConditions.isEmpty()) {
108            throw FlexExceptions.wrap("deleteByMap is not allow empty map.");
109        }
110        return deleteByQuery(QueryWrapper.create().where(whereConditions));
111    }
112
113    /**
114     * 根据条件来删除数据
115     *
116     * @param condition 条件
117     * @return 返回影响的行数
118     */
119    default int deleteByCondition(QueryCondition condition) {
120        return deleteByQuery(QueryWrapper.create().where(condition));
121    }
122
123    /**
124     * 根据 query 构建的条件来数据吗
125     *
126     * @param queryWrapper query 条件
127     * @return 返回影响的行数
128     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteByQuery(Map, ProviderContext)
129     */
130    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteByQuery")
131    int deleteByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
132
133
134    /**
135     * 根据主键来更新数据,若数据为 null,也会更新到数据库
136     *
137     * @param entity 数据内容,必须包含有主键
138     * @return 返回影响的行数
139     */
140    default int update(T entity) {
141        return update(entity, true);
142    }
143
144    /**
145     * 根据主键来更新数据到数据库
146     *
147     * @param entity      数据内容
148     * @param ignoreNulls 是否忽略空内容字段
149     * @return 返回影响的行数
150     * @see com.mybatisflex.core.provider.EntitySqlProvider#update(Map, ProviderContext)
151     */
152    @UpdateProvider(type = EntitySqlProvider.class, method = "update")
153    int update(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
154
155
156    /**
157     * 根据 map 构建的条件来更新数据
158     *
159     * @param entity 数据
160     * @param map    where 条件内容
161     * @return 返回影响的行数
162     */
163    default int updateByMap(T entity, Map<String, Object> map) {
164        return updateByQuery(entity, QueryWrapper.create().where(map));
165    }
166
167    /**
168     * 根据 condition 来更新数据
169     *
170     * @param entity    数据
171     * @param condition 条件
172     * @return 返回影响的行数
173     */
174    default int updateByCondition(T entity, QueryCondition condition) {
175        return updateByQuery(entity, QueryWrapper.create().where(condition));
176    }
177
178    /**
179     * 根据 condition 来更新数据
180     *
181     * @param entity      数据
182     * @param ignoreNulls 是否忽略 null 数据,默认为 true
183     * @param condition   条件
184     * @return 返回影响的行数
185     */
186    default int updateByCondition(T entity, boolean ignoreNulls, QueryCondition condition) {
187        return updateByQuery(entity, ignoreNulls, QueryWrapper.create().where(condition));
188    }
189
190
191    /**
192     * 根据 query 构建的条件来更新数据
193     *
194     * @param entity       数据内容
195     * @param queryWrapper query 条件
196     * @return 返回影响的行数
197     */
198
199    default int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper) {
200        return updateByQuery(entity, true, queryWrapper);
201    }
202
203    /**
204     * 根据 query 构建的条件来更新数据
205     *
206     * @param entity       数据内容
207     * @param ignoreNulls  是否忽略空值
208     * @param queryWrapper query 条件
209     * @see com.mybatisflex.core.provider.EntitySqlProvider#updateByQuery(Map, ProviderContext)
210     */
211    @UpdateProvider(type = EntitySqlProvider.class, method = "updateByQuery")
212    int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
213
214
215    /**
216     * 根据主键来选择数据
217     *
218     * @param id 多个主键
219     * @return entity
220     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectOneById(Map, ProviderContext)
221     */
222    @SelectProvider(type = EntitySqlProvider.class, method = "selectOneById")
223    T selectOneById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
224
225
226    /**
227     * 根据 map 构建的条件来查询数据
228     *
229     * @param whereConditions where 条件
230     * @return entity 数据
231     */
232    default T selectOneByMap(Map<String, Object> whereConditions) {
233        return selectOneByQuery(QueryWrapper.create().where(whereConditions));
234    }
235
236
237    /**
238     * 根据 condition 来查询数据
239     *
240     * @param condition 条件
241     * @return 1 条数据
242     */
243    default T selectOneByCondition(QueryCondition condition) {
244        return selectOneByQuery(QueryWrapper.create().where(condition));
245    }
246
247
248    /**
249     * 根据 queryWrapper 构建的条件来查询 1 条数据
250     *
251     * @param queryWrapper query 条件
252     * @return entity 数据
253     */
254    default T selectOneByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper) {
255        List<T> entities = selectListByQuery(queryWrapper.limit(1));
256        return (entities == null || entities.isEmpty()) ? null : entities.get(0);
257    }
258
259    /**
260     * 根据多个主键来查询多条数据
261     *
262     * @param ids 主键列表
263     * @return 数据列表
264     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByIds(Map, ProviderContext)
265     */
266    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByIds")
267    List<T> selectListByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
268
269
270    /**
271     * 根据 map 来构建查询条件,查询多条数据
272     *
273     * @param whereConditions 条件列表
274     * @return 数据列表
275     */
276    default List<T> selectListByMap(Map<String, Object> whereConditions) {
277        return selectListByQuery(QueryWrapper.create().where(whereConditions));
278    }
279
280
281    /**
282     * 根据 map 来构建查询条件,查询多条数据
283     *
284     * @param whereConditions 条件列表
285     * @return 数据列表
286     */
287    default List<T> selectListByMap(Map<String, Object> whereConditions, int count) {
288        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
289    }
290
291
292    /**
293     * 根据 condition 来查询数据
294     *
295     * @param condition condition 条件
296     * @return 数据列表
297     */
298    default List<T> selectListByCondition(QueryCondition condition) {
299        return selectListByQuery(QueryWrapper.create().where(condition));
300    }
301
302
303    /**
304     * 根据 condition 来查询数据
305     *
306     * @param condition condition 条件
307     * @param count     数据量
308     * @return 数据列表
309     */
310    default List<T> selectListByCondition(QueryCondition condition, int count) {
311        return selectListByQuery(QueryWrapper.create().where(condition).limit(count));
312    }
313
314
315    /**
316     * 根据 query 来构建条件查询数据列表
317     *
318     * @param queryWrapper 查询条件
319     * @return 数据列表
320     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByQuery(Map, ProviderContext)
321     */
322    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
323    List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
324
325
326    /**
327     * 查询全部数据
328     *
329     * @return 数据列表
330     */
331    default List<T> selectAll() {
332        return selectListByQuery(new QueryWrapper());
333    }
334
335
336    /**
337     * 根据条件查询数据总量
338     *
339     * @param condition 条件
340     * @return 数据量
341     */
342    default long selectCountByCondition(QueryCondition condition) {
343        return selectCountByQuery(QueryWrapper.create().where(condition));
344    }
345
346
347    /**
348     * 根据 queryWrapper 来查询数据量
349     *
350     * @param queryWrapper 查询包装器
351     * @return 数据量
352     * @see EntitySqlProvider#selectCountByQuery(Map, ProviderContext)
353     */
354    @SelectProvider(type = EntitySqlProvider.class, method = "selectCountByQuery")
355    long selectCountByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
356
357
358    /**
359     * 分页查询
360     *
361     * @param pageNumber   当前页码
362     * @param pageSize     每页的数据量
363     * @param queryWrapper 查询条件
364     * @return 返回 Page 数据
365     */
366    default Page<T> paginate(int pageNumber, int pageSize, QueryWrapper queryWrapper) {
367        Page<T> page = new Page<>(pageNumber, pageSize);
368        return paginate(page, queryWrapper);
369    }
370
371
372    /**
373     * 根据条件分页查询
374     *
375     * @param pageNumber 当前页面
376     * @param pageSize   每页的数据量
377     * @param condition  查询条件
378     * @return 返回 Page 数据
379     */
380    default Page<T> paginate(int pageNumber, int pageSize, QueryCondition condition) {
381        Page<T> page = new Page<>(pageNumber, pageSize);
382        return paginate(page, new QueryWrapper().where(condition));
383    }
384
385    /**
386     * 分页查询
387     *
388     * @param pageNumber   当前页码
389     * @param pageSize     每页的数据量
390     * @param totalRow     数据总量
391     * @param queryWrapper 查询条件
392     * @return 返回 Page 数据
393     */
394    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper) {
395        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
396        return paginate(page, queryWrapper);
397    }
398
399
400    /**
401     * 根据条件分页查询
402     *
403     * @param pageNumber 当前页面
404     * @param pageSize   每页的数据量
405     * @param totalRow   数据总量
406     * @param condition  查询条件
407     * @return 返回 Page 数据
408     */
409    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryCondition condition) {
410        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
411        return paginate(page, new QueryWrapper().where(condition));
412    }
413
414
415    /**
416     * 分页查询
417     *
418     * @param page         page,其包含了页码、每页的数据量,可能包含数据总量
419     * @param queryWrapper 查询条件
420     * @return page 数据
421     */
422    default Page<T> paginate(@Param("page") Page<T> page, @Param("query") QueryWrapper queryWrapper) {
423
424        List<QueryColumn> groupByColumns = null;
425
426        // 只有 totalRow 小于 0 的时候才会去查询总量
427        // 这样方便用户做总数缓存,而非每次都要去查询总量
428        // 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
429        if (page.getTotalRow() < 0) {
430            groupByColumns = CPI.getGroupByColumns(queryWrapper);
431            //清除group by 去查询数据
432            CPI.setGroupByColumns(queryWrapper, null);
433            long count = selectCountByQuery(queryWrapper);
434            page.setTotalRow(count);
435        }
436
437        if (page.getTotalRow() == 0 || page.getPageNumber() > page.getTotalPage()) {
438            return page;
439        }
440
441        //恢复数量查询清除的 groupBy
442        if (groupByColumns != null) {
443            CPI.setGroupByColumns(queryWrapper, groupByColumns);
444        }
445
446        int offset = page.getPageSize() * (page.getPageNumber() - 1);
447        queryWrapper.limit(offset, page.getPageSize());
448        List<T> rows = selectListByQuery(queryWrapper);
449        page.setRecords(rows);
450        return page;
451    }
452}