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     */
044    default int insert(T entity){
045        return insert(entity,false);
046    }
047
048
049    /**
050     * 插入 entity 数据,但是忽略 null 的数据,只对有值的内容进行插入
051     * 这样的好处是数据库已经配置了一些默认值,这些默认值才会生效
052     *
053     * @param entity 实体类
054     * @return 返回影响的行数
055     */
056    default int insertSelective(T entity){
057        return insert(entity,true);
058    }
059
060
061
062    /**
063     * 插入 entity 数据
064     *
065     * @param entity 实体类
066     * @return 返回影响的行数
067     * @see com.mybatisflex.core.provider.EntitySqlProvider#insert(Map, ProviderContext)
068     */
069    @InsertProvider(type = EntitySqlProvider.class, method = "insert")
070    int insert(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
071
072
073
074    /**
075     * 批量插入 entity 数据,只会根据第一条数据来构建插入的字段内容
076     *
077     * @param entities 插入的数据列表
078     * @return 返回影响的行数
079     * @see com.mybatisflex.core.provider.EntitySqlProvider#insertBatch(Map, ProviderContext)
080     * @see com.mybatisflex.core.FlexConsts#METHOD_INSERT_BATCH
081     */
082    @InsertProvider(type = EntitySqlProvider.class, method = FlexConsts.METHOD_INSERT_BATCH)
083    int insertBatch(@Param(FlexConsts.ENTITIES) List<T> entities);
084
085
086    /**
087     * 新增 或者 更新,若主键有值,则更新,若没有主键值,则插入
088     *
089     * @param entity 实体类
090     * @return 返回影响的行数
091     */
092    default int insertOrUpdate(T entity) {
093        TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass());
094        Object[] pkArgs = tableInfo.buildPkSqlArgs(entity);
095        if (pkArgs.length == 0 || pkArgs[0] == null) {
096            return insert(entity);
097        } else {
098            return update(entity);
099        }
100    }
101
102    /**
103     * 根据 id 删除数据
104     * 如果是多个主键的情况下,需要传入数组 new Object[]{100,101}
105     *
106     * @param id 主键数据
107     * @return 返回影响的行数
108     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteById(Map, ProviderContext)
109     */
110    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteById")
111    int deleteById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
112
113
114    /**
115     * 根据多个 id 批量删除数据
116     *
117     * @param ids ids 列表
118     * @return 返回影响的行数
119     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext)
120     */
121    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteBatchByIds")
122    int deleteBatchByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
123
124
125    /**
126     * 根据 map 构建的条件来删除数据
127     *
128     * @param whereConditions 条件
129     * @return 返回影响的行数
130     */
131    default int deleteByMap(Map<String, Object> whereConditions) {
132        if (ObjectUtil.areNull(whereConditions) || whereConditions.isEmpty()) {
133            throw FlexExceptions.wrap("deleteByMap is not allow empty map.");
134        }
135        return deleteByQuery(QueryWrapper.create().where(whereConditions));
136    }
137
138    /**
139     * 根据条件来删除数据
140     *
141     * @param condition 条件
142     * @return 返回影响的行数
143     */
144    default int deleteByCondition(QueryCondition condition) {
145        return deleteByQuery(QueryWrapper.create().where(condition));
146    }
147
148    /**
149     * 根据 query 构建的条件来数据吗
150     *
151     * @param queryWrapper query 条件
152     * @return 返回影响的行数
153     * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteByQuery(Map, ProviderContext)
154     */
155    @DeleteProvider(type = EntitySqlProvider.class, method = "deleteByQuery")
156    int deleteByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
157
158
159    /**
160     * 根据主键来更新数据,若数据为 null,也会更新到数据库
161     *
162     * @param entity 数据内容,必须包含有主键
163     * @return 返回影响的行数
164     */
165    default int update(T entity) {
166        return update(entity, true);
167    }
168
169    /**
170     * 根据主键来更新数据到数据库
171     *
172     * @param entity      数据内容
173     * @param ignoreNulls 是否忽略空内容字段
174     * @return 返回影响的行数
175     * @see com.mybatisflex.core.provider.EntitySqlProvider#update(Map, ProviderContext)
176     */
177    @UpdateProvider(type = EntitySqlProvider.class, method = "update")
178    int update(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls);
179
180
181    /**
182     * 根据 map 构建的条件来更新数据
183     *
184     * @param entity 数据
185     * @param map    where 条件内容
186     * @return 返回影响的行数
187     */
188    default int updateByMap(T entity, Map<String, Object> map) {
189        return updateByQuery(entity, QueryWrapper.create().where(map));
190    }
191
192    /**
193     * 根据 condition 来更新数据
194     *
195     * @param entity    数据
196     * @param condition 条件
197     * @return 返回影响的行数
198     */
199    default int updateByCondition(T entity, QueryCondition condition) {
200        return updateByQuery(entity, QueryWrapper.create().where(condition));
201    }
202
203    /**
204     * 根据 condition 来更新数据
205     *
206     * @param entity      数据
207     * @param ignoreNulls 是否忽略 null 数据,默认为 true
208     * @param condition   条件
209     * @return 返回影响的行数
210     */
211    default int updateByCondition(T entity, boolean ignoreNulls, QueryCondition condition) {
212        return updateByQuery(entity, ignoreNulls, QueryWrapper.create().where(condition));
213    }
214
215
216    /**
217     * 根据 query 构建的条件来更新数据
218     *
219     * @param entity       数据内容
220     * @param queryWrapper query 条件
221     * @return 返回影响的行数
222     */
223
224    default int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper) {
225        return updateByQuery(entity, true, queryWrapper);
226    }
227
228    /**
229     * 根据 query 构建的条件来更新数据
230     *
231     * @param entity       数据内容
232     * @param ignoreNulls  是否忽略空值
233     * @param queryWrapper query 条件
234     * @see com.mybatisflex.core.provider.EntitySqlProvider#updateByQuery(Map, ProviderContext)
235     */
236    @UpdateProvider(type = EntitySqlProvider.class, method = "updateByQuery")
237    int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
238
239
240    /**
241     * 根据主键来选择数据
242     *
243     * @param id 多个主键
244     * @return entity
245     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectOneById(Map, ProviderContext)
246     */
247    @SelectProvider(type = EntitySqlProvider.class, method = "selectOneById")
248    T selectOneById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id);
249
250
251    /**
252     * 根据 map 构建的条件来查询数据
253     *
254     * @param whereConditions where 条件
255     * @return entity 数据
256     */
257    default T selectOneByMap(Map<String, Object> whereConditions) {
258        return selectOneByQuery(QueryWrapper.create().where(whereConditions));
259    }
260
261
262    /**
263     * 根据 condition 来查询数据
264     *
265     * @param condition 条件
266     * @return 1 条数据
267     */
268    default T selectOneByCondition(QueryCondition condition) {
269        return selectOneByQuery(QueryWrapper.create().where(condition));
270    }
271
272
273    /**
274     * 根据 queryWrapper 构建的条件来查询 1 条数据
275     *
276     * @param queryWrapper query 条件
277     * @return entity 数据
278     */
279    default T selectOneByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper) {
280        List<T> entities = selectListByQuery(queryWrapper.limit(1));
281        return (entities == null || entities.isEmpty()) ? null : entities.get(0);
282    }
283
284    /**
285     * 根据多个主键来查询多条数据
286     *
287     * @param ids 主键列表
288     * @return 数据列表
289     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByIds(Map, ProviderContext)
290     */
291    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByIds")
292    List<T> selectListByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids);
293
294
295    /**
296     * 根据 map 来构建查询条件,查询多条数据
297     *
298     * @param whereConditions 条件列表
299     * @return 数据列表
300     */
301    default List<T> selectListByMap(Map<String, Object> whereConditions) {
302        return selectListByQuery(QueryWrapper.create().where(whereConditions));
303    }
304
305
306    /**
307     * 根据 map 来构建查询条件,查询多条数据
308     *
309     * @param whereConditions 条件列表
310     * @return 数据列表
311     */
312    default List<T> selectListByMap(Map<String, Object> whereConditions, int count) {
313        return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count));
314    }
315
316
317    /**
318     * 根据 condition 来查询数据
319     *
320     * @param condition condition 条件
321     * @return 数据列表
322     */
323    default List<T> selectListByCondition(QueryCondition condition) {
324        return selectListByQuery(QueryWrapper.create().where(condition));
325    }
326
327
328    /**
329     * 根据 condition 来查询数据
330     *
331     * @param condition condition 条件
332     * @param count     数据量
333     * @return 数据列表
334     */
335    default List<T> selectListByCondition(QueryCondition condition, int count) {
336        return selectListByQuery(QueryWrapper.create().where(condition).limit(count));
337    }
338
339
340    /**
341     * 根据 query 来构建条件查询数据列表
342     *
343     * @param queryWrapper 查询条件
344     * @return 数据列表
345     * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByQuery(Map, ProviderContext)
346     */
347    @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
348    List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
349
350
351    /**
352     * 查询全部数据
353     *
354     * @return 数据列表
355     */
356    default List<T> selectAll() {
357        return selectListByQuery(new QueryWrapper());
358    }
359
360
361    /**
362     * 根据条件查询数据总量
363     *
364     * @param condition 条件
365     * @return 数据量
366     */
367    default long selectCountByCondition(QueryCondition condition) {
368        return selectCountByQuery(QueryWrapper.create().where(condition));
369    }
370
371
372    /**
373     * 根据 queryWrapper 来查询数据量
374     *
375     * @param queryWrapper 查询包装器
376     * @return 数据量
377     * @see EntitySqlProvider#selectCountByQuery(Map, ProviderContext)
378     */
379    @SelectProvider(type = EntitySqlProvider.class, method = "selectCountByQuery")
380    long selectCountByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
381
382
383    /**
384     * 分页查询
385     *
386     * @param pageNumber   当前页码
387     * @param pageSize     每页的数据量
388     * @param queryWrapper 查询条件
389     * @return 返回 Page 数据
390     */
391    default Page<T> paginate(int pageNumber, int pageSize, QueryWrapper queryWrapper) {
392        Page<T> page = new Page<>(pageNumber, pageSize);
393        return paginate(page, queryWrapper);
394    }
395
396
397    /**
398     * 根据条件分页查询
399     *
400     * @param pageNumber 当前页面
401     * @param pageSize   每页的数据量
402     * @param condition  查询条件
403     * @return 返回 Page 数据
404     */
405    default Page<T> paginate(int pageNumber, int pageSize, QueryCondition condition) {
406        Page<T> page = new Page<>(pageNumber, pageSize);
407        return paginate(page, new QueryWrapper().where(condition));
408    }
409
410    /**
411     * 分页查询
412     *
413     * @param pageNumber   当前页码
414     * @param pageSize     每页的数据量
415     * @param totalRow     数据总量
416     * @param queryWrapper 查询条件
417     * @return 返回 Page 数据
418     */
419    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper) {
420        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
421        return paginate(page, queryWrapper);
422    }
423
424
425    /**
426     * 根据条件分页查询
427     *
428     * @param pageNumber 当前页面
429     * @param pageSize   每页的数据量
430     * @param totalRow   数据总量
431     * @param condition  查询条件
432     * @return 返回 Page 数据
433     */
434    default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryCondition condition) {
435        Page<T> page = new Page<>(pageNumber, pageSize, totalRow);
436        return paginate(page, new QueryWrapper().where(condition));
437    }
438
439
440    /**
441     * 分页查询
442     *
443     * @param page         page,其包含了页码、每页的数据量,可能包含数据总量
444     * @param queryWrapper 查询条件
445     * @return page 数据
446     */
447    default Page<T> paginate(@Param("page") Page<T> page, @Param("query") QueryWrapper queryWrapper) {
448
449        List<QueryColumn> groupByColumns = null;
450
451        // 只有 totalRow 小于 0 的时候才会去查询总量
452        // 这样方便用户做总数缓存,而非每次都要去查询总量
453        // 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
454        if (page.getTotalRow() < 0) {
455            groupByColumns = CPI.getGroupByColumns(queryWrapper);
456            //清除group by 去查询数据
457            CPI.setGroupByColumns(queryWrapper, null);
458            long count = selectCountByQuery(queryWrapper);
459            page.setTotalRow(count);
460        }
461
462        if (page.getTotalRow() == 0 || page.getPageNumber() > page.getTotalPage()) {
463            return page;
464        }
465
466        //恢复数量查询清除的 groupBy
467        if (groupByColumns != null) {
468            CPI.setGroupByColumns(queryWrapper, groupByColumns);
469        }
470
471        int offset = page.getPageSize() * (page.getPageNumber() - 1);
472        queryWrapper.limit(offset, page.getPageSize());
473        List<T> rows = selectListByQuery(queryWrapper);
474        page.setRecords(rows);
475        return page;
476    }
477}