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.service;
017
018import com.mybatisflex.core.BaseMapper;
019import com.mybatisflex.core.exception.FlexExceptions;
020import com.mybatisflex.core.paginate.Page;
021import com.mybatisflex.core.query.*;
022import com.mybatisflex.core.row.Db;
023import com.mybatisflex.core.update.UpdateChain;
024import com.mybatisflex.core.util.ClassUtil;
025import com.mybatisflex.core.util.CollectionUtil;
026import com.mybatisflex.core.util.SqlUtil;
027
028import java.io.Serializable;
029import java.util.Collection;
030import java.util.List;
031import java.util.Map;
032import java.util.Optional;
033
034
035/**
036 * 由 Mybatis-Flex 提供的顶级增强 Service 接口。
037 *
038 * @param <T> 实体类(Entity)类型
039 * @author 王帅
040 * @since 2023-05-01
041 */
042@SuppressWarnings({"unused", "unchecked"})
043public interface IService<T> {
044
045    int DEFAULT_BATCH_SIZE = 1000;
046
047    /**
048     * <p>获取对应实体类(Entity)的基础映射类(BaseMapper)。
049     *
050     * @return 基础映射类(BaseMapper)
051     */
052    BaseMapper<T> getMapper();
053
054    // ===== 保存(增)操作 =====
055
056    /**
057     * <p>保存实体类对象数据。
058     *
059     * @param entity 实体类对象
060     * @return {@code true} 保存成功,{@code false} 保存失败。
061     * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类
062     * {@code null} 属性的数据,使数据库配置的默认值生效。
063     */
064    default boolean save(T entity) {
065        return SqlUtil.toBool(getMapper().insert(entity, true));
066    }
067
068    /**
069     * <p>批量保存实体类对象数据。
070     *
071     * @param entities 实体类对象
072     * @return {@code true} 保存成功,{@code false} 保存失败。
073     * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类
074     * {@code null} 属性的数据,使数据库配置的默认值生效。
075     */
076    default boolean saveBatch(Collection<T> entities) {
077        return saveBatch(entities, DEFAULT_BATCH_SIZE);
078    }
079
080    /**
081     * <p>批量保存实体类对象数据。
082     *
083     * @param entities  实体类对象
084     * @param batchSize 每次保存切分的数量
085     * @return {@code true} 保存成功,{@code false} 保存失败。
086     * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类
087     * {@code null} 属性的数据,使数据库配置的默认值生效。
088     */
089    default boolean saveBatch(Collection<T> entities, int batchSize) {
090        Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
091        return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertSelective));
092    }
093
094    /**
095     * <p>保存或者更新实体类对象数据。
096     *
097     * @param entity 实体类对象
098     * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。
099     * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类
100     * {@code null} 属性的数据。
101     */
102    default boolean saveOrUpdate(T entity) {
103        return SqlUtil.toBool(getMapper().insertOrUpdate(entity, true));
104    }
105
106    /**
107     * <p>保存或者更新实体类对象数据。
108     *
109     * @param entities 实体类对象
110     * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。
111     * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类
112     * {@code null} 属性的数据。
113     */
114    default boolean saveOrUpdateBatch(Collection<T> entities) {
115        return saveOrUpdateBatch(entities, DEFAULT_BATCH_SIZE);
116    }
117
118    /**
119     * <p>保存或者更新实体类对象数据。
120     *
121     * @param entities  实体类对象
122     * @param batchSize 每次操作切分的数量
123     * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。
124     * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类
125     * {@code null} 属性的数据。
126     */
127    default boolean saveOrUpdateBatch(Collection<T> entities, int batchSize) {
128        Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
129        return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertOrUpdateSelective));
130    }
131
132    // ===== 删除(删)操作 =====
133
134    /**
135     * <p>根据查询条件删除数据。
136     *
137     * @param query 查询条件
138     * @return {@code true} 删除成功,{@code false} 删除失败。
139     */
140    default boolean remove(QueryWrapper query) {
141        return SqlUtil.toBool(getMapper().deleteByQuery(query));
142    }
143
144    /**
145     * <p>根据查询条件删除数据。
146     *
147     * @param condition 查询条件
148     * @return {@code true} 删除成功,{@code false} 删除失败。
149     */
150    default boolean remove(QueryCondition condition) {
151        return remove(query().where(condition));
152    }
153
154    /**
155     * <p>根据数据主键删除数据。
156     *
157     * @param id 数据主键
158     * @return {@code true} 删除成功,{@code false} 删除失败。
159     */
160    default boolean removeById(Serializable id) {
161        return SqlUtil.toBool(getMapper().deleteById(id));
162    }
163
164    /**
165     * <p>根据数据主键批量删除数据。
166     *
167     * @param ids 数据主键
168     * @return {@code true} 删除成功,{@code false} 删除失败。
169     */
170    default boolean removeByIds(Collection<? extends Serializable> ids) {
171        if (CollectionUtil.isEmpty(ids)) {
172            return false;
173        }
174        return SqlUtil.toBool(getMapper().deleteBatchByIds(ids));
175    }
176
177    /**
178     * <p>根据 {@link Map} 构建查询条件删除数据。
179     *
180     * @param query 查询条件
181     * @return {@code true} 删除成功,{@code false} 删除失败。
182     */
183    default boolean removeByMap(Map<String, Object> query) {
184        // 防止全表删除
185        if (query == null || query.isEmpty()) {
186            throw FlexExceptions.wrap("deleteByMap is not allow empty map.");
187        }
188        return remove(query().where(query));
189    }
190
191    // ===== 更新(改)操作 =====
192
193    /**
194     * <p>根据数据主键更新数据。
195     *
196     * @param entity 实体类对象
197     * @return {@code true} 更新成功,{@code false} 更新失败。
198     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
199     */
200    default boolean updateById(T entity) {
201        return updateById(entity, true);
202    }
203
204    /**
205     * 根据主键更新数据
206     *
207     * @param entity      实体对象
208     * @param ignoreNulls 是否忽略 null 值
209     * @return {@code true} 更新成功,{@code false} 更新失败。
210     */
211    default boolean updateById(T entity, boolean ignoreNulls) {
212        return SqlUtil.toBool(getMapper().update(entity, ignoreNulls));
213    }
214
215    /**
216     * <p>根据 {@link Map} 构建查询条件更新数据。
217     *
218     * @param entity 实体类对象
219     * @param query  查询条件
220     * @return {@code true} 更新成功,{@code false} 更新失败。
221     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
222     */
223    default boolean update(T entity, Map<String, Object> query) {
224        return update(entity, query().where(query));
225    }
226
227    /**
228     * <p>根据查询条件更新数据。
229     *
230     * @param entity 实体类对象
231     * @param query  查询条件
232     * @return {@code true} 更新成功,{@code false} 更新失败。
233     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
234     */
235    default boolean update(T entity, QueryWrapper query) {
236        return SqlUtil.toBool(getMapper().updateByQuery(entity, query));
237    }
238
239    /**
240     * <p>根据查询条件更新数据。
241     *
242     * @param entity    实体类对象
243     * @param condition 查询条件
244     * @return {@code true} 更新成功,{@code false} 更新失败。
245     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
246     */
247    default boolean update(T entity, QueryCondition condition) {
248        return update(entity, query().where(condition));
249    }
250
251    /**
252     * <p>根据数据主键批量更新数据
253     *
254     * @param entities 实体类对象集合
255     * @return boolean {@code true} 更新成功,{@code false} 更新失败。
256     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
257     */
258    default boolean updateBatch(Collection<T> entities) {
259        return updateBatch(entities, DEFAULT_BATCH_SIZE);
260    }
261
262    /**
263     * <p>根据数据主键批量更新数据
264     *
265     * @param entities  实体类对象集合
266     * @param batchSize 每批次更新数量
267     * @return {@code true} 更新成功,{@code false} 更新失败。
268     * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。
269     */
270    default boolean updateBatch(Collection<T> entities, int batchSize) {
271        Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
272        return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::update));
273    }
274
275    // ===== 查询(查)操作 =====
276
277    /**
278     * <p>根据数据主键查询一条数据。
279     *
280     * @param id 数据主键
281     * @return 查询结果数据
282     */
283    default T getById(Serializable id) {
284        return getMapper().selectOneById(id);
285    }
286
287    /**
288     * <p>根据数据主键查询一条数据。
289     *
290     * @param id 数据主键
291     * @return 查询结果数据
292     * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。
293     */
294    default Optional<T> getByIdOpt(Serializable id) {
295        return Optional.ofNullable(getById(id));
296    }
297
298    /**
299     * <p>根据查询条件查询一条数据。
300     *
301     * @param query 查询条件
302     * @return 查询结果数据
303     */
304    default T getOne(QueryWrapper query) {
305        return getMapper().selectOneByQuery(query);
306    }
307
308    /**
309     * <p>根据查询条件查询一条数据。
310     *
311     * @param query 查询条件
312     * @return 查询结果数据
313     * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。
314     */
315    default Optional<T> getOneOpt(QueryWrapper query) {
316        return Optional.ofNullable(getOne(query));
317    }
318
319    /**
320     * <p>根据查询条件查询一条数据,并通过 asType 进行接收。
321     *
322     * @param query  查询条件
323     * @param asType 接收的数据类型
324     * @return 查询结果数据
325     */
326    default <R> R getOneAs(QueryWrapper query, Class<R> asType) {
327        return getMapper().selectOneByQueryAs(query, asType);
328    }
329
330    /**
331     * <p>根据查询条件查询一条数据。
332     *
333     * @param query  查询条件
334     * @param asType 接收的数据类型
335     * @return 查询结果数据
336     * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。
337     */
338    default <R> Optional<R> getOneAsOpt(QueryWrapper query, Class<R> asType) {
339        return Optional.ofNullable(getOneAs(query, asType));
340    }
341
342    /**
343     * <p>根据查询条件查询一条数据。
344     *
345     * @param condition 查询条件
346     * @return 查询结果数据
347     */
348    default T getOne(QueryCondition condition) {
349        return getOne(query().where(condition));
350    }
351
352    /**
353     * <p>根据查询条件查询一条数据。
354     *
355     * @param condition 查询条件
356     * @return 查询结果数据
357     * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。
358     */
359    default Optional<T> getOneOpt(QueryCondition condition) {
360        return Optional.ofNullable(getOne(condition));
361    }
362
363    /**
364     * <p>查询结果集中第一列,且第一条数据。
365     *
366     * @param query 查询条件
367     * @return 数据值
368     */
369    default Object getObj(QueryWrapper query) {
370        return getMapper().selectObjectByQuery(query);
371    }
372
373    /**
374     * <p>查询结果集中第一列,且第一条数据,并封装为 {@link Optional} 返回。
375     *
376     * @param query 查询条件
377     * @return 数据值
378     */
379    default Optional<Object> getObjOpt(QueryWrapper query) {
380        return Optional.ofNullable(getObj(query));
381    }
382
383    /**
384     * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。
385     *
386     * @param query  查询条件
387     * @param asType 接收的数据类型
388     * @return 数据值
389     */
390    default <R> R getObjAs(QueryWrapper query, Class<R> asType) {
391        return getMapper().selectObjectByQueryAs(query, asType);
392    }
393
394    /**
395     * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String}
396     * 等,封装为 {@link Optional} 返回。
397     *
398     * @param query  查询条件
399     * @param asType 接收的数据类型
400     * @return 数据值
401     */
402    default <R> Optional<R> getObjAsOpt(QueryWrapper query, Class<R> asType) {
403        return Optional.ofNullable(getObjAs(query, asType));
404    }
405
406    /**
407     * <p>查询结果集中第一列所有数据。
408     *
409     * @param query 查询条件
410     * @return 数据列表
411     */
412    default List<Object> objList(QueryWrapper query) {
413        return getMapper().selectObjectListByQuery(query);
414    }
415
416    /**
417     * <p>查询结果集中第一列所有数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。
418     *
419     * @param query  查询条件
420     * @param asType 接收的数据类型
421     * @return 数据列表
422     */
423    default <R> List<R> objListAs(QueryWrapper query, Class<R> asType) {
424        return getMapper().selectObjectListByQueryAs(query, asType);
425    }
426
427    /**
428     * <p>查询所有数据。
429     *
430     * @return 所有数据
431     */
432    default List<T> list() {
433        return list(query());
434    }
435
436    /**
437     * <p>根据查询条件查询数据集合。
438     *
439     * @param query 查询条件
440     * @return 数据集合
441     */
442    default List<T> list(QueryWrapper query) {
443        return getMapper().selectListByQuery(query);
444    }
445
446    /**
447     * <p>根据查询条件查询数据集合。
448     *
449     * @param condition 查询条件
450     * @return 数据集合
451     */
452    default List<T> list(QueryCondition condition) {
453        return list(query().where(condition));
454    }
455
456    /**
457     * <p>根据查询条件查询数据集合,并通过 asType 进行接收。
458     *
459     * @param query  查询条件
460     * @param asType 接收的数据类型
461     * @return 数据集合
462     */
463    default <R> List<R> listAs(QueryWrapper query, Class<R> asType) {
464        return getMapper().selectListByQueryAs(query, asType);
465    }
466
467    /**
468     * <p>根据数据主键查询数据集合。
469     *
470     * @param ids 数据主键
471     * @return 数据集合
472     */
473    default List<T> listByIds(Collection<? extends Serializable> ids) {
474        return getMapper().selectListByIds(ids);
475    }
476
477    /**
478     * <p>根据 {@link Map} 构建查询条件查询数据集合。
479     *
480     * @param query 查询条件
481     * @return 数据集合
482     */
483    default List<T> listByMap(Map<String, Object> query) {
484        return list(query().where(query));
485    }
486
487    // ===== 数量查询操作 =====
488
489    /**
490     * <p>根据查询条件判断数据是否存在。
491     *
492     * @param query 查询条件
493     * @return {@code true} 数据存在,{@code false} 数据不存在。
494     */
495    default boolean exists(QueryWrapper query) {
496        return exists(CPI.getWhereQueryCondition(query));
497    }
498
499    /**
500     * <p>根据查询条件判断数据是否存在。
501     *
502     * @param condition 查询条件
503     * @return {@code true} 数据存在,{@code false} 数据不存在。
504     */
505    default boolean exists(QueryCondition condition) {
506        // 根据查询条件构建 SQL 语句
507        // SELECT 1 FROM table WHERE ... LIMIT 1
508        QueryWrapper queryWrapper = QueryMethods.selectOne()
509            .where(condition)
510            .limit(1);
511        // 获取数据集合,空集合:[] 不存在数据,有一个元素的集合:[1] 存在数据
512        List<Object> objects = getMapper().selectObjectListByQuery(queryWrapper);
513        // 判断是否存在数据
514        return CollectionUtil.isNotEmpty(objects);
515    }
516
517    /**
518     * <p>查询所有数据数量。
519     *
520     * @return 所有数据数量
521     */
522    default long count() {
523        return count(query());
524    }
525
526    /**
527     * <p>根据查询条件查询数据数量。
528     *
529     * @param query 查询条件
530     * @return 数据数量
531     */
532    default long count(QueryWrapper query) {
533        return getMapper().selectCountByQuery(query);
534    }
535
536    /**
537     * <p>根据查询条件查询数据数量。
538     *
539     * @param condition 查询条件
540     * @return 数据数量
541     */
542    default long count(QueryCondition condition) {
543        return count(query().where(condition));
544    }
545
546    // ===== 分页查询操作 =====
547
548    /**
549     * <p>分页查询所有数据。
550     *
551     * @param page 分页对象
552     * @return 分页对象
553     */
554    default Page<T> page(Page<T> page) {
555        return page(page, query());
556    }
557
558    /**
559     * <p>根据查询条件分页查询数据。
560     *
561     * @param page  分页对象
562     * @param query 查询条件
563     * @return 分页对象
564     */
565    default Page<T> page(Page<T> page, QueryWrapper query) {
566        return pageAs(page, query, null);
567    }
568
569    /**
570     * <p>根据查询条件分页查询数据。
571     *
572     * @param page      分页对象
573     * @param condition 查询条件
574     * @return 分页对象
575     */
576    default Page<T> page(Page<T> page, QueryCondition condition) {
577        return page(page, query().where(condition));
578    }
579
580    /**
581     * <p>根据查询条件分页查询数据,并通过 asType 进行接收。
582     *
583     * @param page   分页对象
584     * @param query  查询条件
585     * @param asType 接收的数据类型
586     * @return 分页对象
587     */
588    default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) {
589        return getMapper().paginateAs(page, query, asType);
590    }
591
592    // ===== 查询包装器操作 =====
593
594    /**
595     * 默认 {@link QueryWrapper} 构建。
596     *
597     * @return {@link QueryWrapper} 对象
598     */
599    default QueryWrapper query() {
600        return QueryWrapper.create();
601    }
602
603    /**
604     * 链式查询。
605     *
606     * @return {@link QueryChain} 对象
607     */
608    default QueryChain<T> queryChain() {
609        return QueryChain.of(getMapper());
610    }
611
612    /**
613     * 链式更新。
614     *
615     * @return {@link UpdateChain} 对象
616     */
617    default UpdateChain<T> updateChain() {
618        return UpdateChain.create(getMapper());
619    }
620
621}