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}