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.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 //region ===== 保存(增)操作 ===== 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 //endregion ===== 保存(增)操作 ===== 132 133 //region ===== 删除(删)操作 ===== 134 135 /** 136 * <p>根据查询条件删除数据。 137 * 138 * @param query 查询条件 139 * @return {@code true} 删除成功,{@code false} 删除失败。 140 */ 141 default boolean remove(QueryWrapper query) { 142 return SqlUtil.toBool(getMapper().deleteByQuery(query)); 143 } 144 145 /** 146 * <p>根据查询条件删除数据。 147 * 148 * @param condition 查询条件 149 * @return {@code true} 删除成功,{@code false} 删除失败。 150 */ 151 default boolean remove(QueryCondition condition) { 152 return remove(query().where(condition)); 153 } 154 155 /** 156 * <p>根据实体主键删除数据。 157 * 158 * @param entity 实体类对象 159 * @return {@code true} 删除成功,{@code false} 删除失败。 160 */ 161 default boolean removeById(T entity) { 162 return SqlUtil.toBool(getMapper().delete(entity)); 163 } 164 165 /** 166 * <p>根据数据主键删除数据。 167 * 168 * @param id 数据主键 169 * @return {@code true} 删除成功,{@code false} 删除失败。 170 */ 171 default boolean removeById(Serializable id) { 172 return SqlUtil.toBool(getMapper().deleteById(id)); 173 } 174 175 /** 176 * <p>根据数据主键批量删除数据。 177 * 178 * @param ids 数据主键 179 * @return {@code true} 删除成功,{@code false} 删除失败。 180 */ 181 default boolean removeByIds(Collection<? extends Serializable> ids) { 182 if (CollectionUtil.isEmpty(ids)) { 183 return false; 184 } 185 return SqlUtil.toBool(getMapper().deleteBatchByIds(ids)); 186 } 187 188 /** 189 * <p>根据 {@link Map} 构建查询条件删除数据。 190 * 191 * @param query 查询条件 192 * @return {@code true} 删除成功,{@code false} 删除失败。 193 */ 194 default boolean removeByMap(Map<String, Object> query) { 195 // 防止全表删除 196 if (query == null || query.isEmpty()) { 197 throw FlexExceptions.wrap("deleteByMap is not allow empty map."); 198 } 199 return remove(query().where(query)); 200 } 201 //endregion ===== 删除(删)操作 ===== 202 203 //region ===== 更新(改)操作 ===== 204 205 /** 206 * <p>根据数据主键更新数据。 207 * 208 * @param entity 实体类对象 209 * @return {@code true} 更新成功,{@code false} 更新失败。 210 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 211 */ 212 default boolean updateById(T entity) { 213 return updateById(entity, true); 214 } 215 216 /** 217 * 根据主键更新数据 218 * 219 * @param entity 实体对象 220 * @param ignoreNulls 是否忽略 null 值 221 * @return {@code true} 更新成功,{@code false} 更新失败。 222 */ 223 default boolean updateById(T entity, boolean ignoreNulls) { 224 return SqlUtil.toBool(getMapper().update(entity, ignoreNulls)); 225 } 226 227 /** 228 * <p>根据 {@link Map} 构建查询条件更新数据。 229 * 230 * @param entity 实体类对象 231 * @param query 查询条件 232 * @return {@code true} 更新成功,{@code false} 更新失败。 233 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 234 */ 235 default boolean update(T entity, Map<String, Object> query) { 236 return update(entity, query().where(query)); 237 } 238 239 /** 240 * <p>根据查询条件更新数据。 241 * 242 * @param entity 实体类对象 243 * @param query 查询条件 244 * @return {@code true} 更新成功,{@code false} 更新失败。 245 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 246 */ 247 default boolean update(T entity, QueryWrapper query) { 248 return SqlUtil.toBool(getMapper().updateByQuery(entity, query)); 249 } 250 251 /** 252 * <p>根据查询条件更新数据。 253 * 254 * @param entity 实体类对象 255 * @param condition 查询条件 256 * @return {@code true} 更新成功,{@code false} 更新失败。 257 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 258 */ 259 default boolean update(T entity, QueryCondition condition) { 260 return update(entity, query().where(condition)); 261 } 262 263 /** 264 * <p>根据数据主键批量更新数据 265 * 266 * @param entities 实体类对象集合 267 * @return boolean {@code true} 更新成功,{@code false} 更新失败。 268 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 269 */ 270 default boolean updateBatch(Collection<T> entities) { 271 return updateBatch(entities, DEFAULT_BATCH_SIZE); 272 } 273 274 275 /** 276 * <p>根据数据主键批量更新数据 277 * 278 * @param entities 实体类对象集合 279 * @param ignoreNulls 是否忽略空字段 280 * {@code true} 表示忽略实体类中为 {@code null} 的字段,不更新这些字段。 281 * {@code false} 表示不忽略空字段,允许将对应字段更新为 {@code null}。 282 * @return boolean {@code true} 更新成功,{@code false} 更新失败。 283 * @apiNote 若 {@code ignoreNulls} 为 {@code true},实体类中为 {@code null} 的属性不会更新到数据库。 284 */ 285 default boolean updateBatch(Collection<T> entities, boolean ignoreNulls) { 286 return updateBatch(entities, DEFAULT_BATCH_SIZE, ignoreNulls); 287 } 288 289 /** 290 * <p>根据数据主键批量更新数据 291 * 292 * @param entities 实体类对象集合 293 * @param batchSize 每批次更新数量 294 * @return {@code true} 更新成功,{@code false} 更新失败。 295 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 296 */ 297 default boolean updateBatch(Collection<T> entities, int batchSize) { 298 Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 299 return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::update)); 300 } 301 302 303 /** 304 * <p>根据数据主键批量更新数据 305 * 306 * @param entities 实体类对象集合 307 * @param batchSize 每批次更新数量 308 * @param ignoreNulls 是否忽略空字段 309 * {@code true} 表示忽略实体类中为 {@code null} 的字段,不更新这些字段。 310 * {@code false} 表示不忽略空字段,允许将对应字段更新为 {@code null}。 311 * @return {@code true} 更新成功,{@code false} 更新失败。 312 * @apiNote 若 {@code ignoreNulls} 为 {@code true},实体类中为 {@code null} 的属性不会更新到数据库。 313 */ 314 default boolean updateBatch(Collection<T> entities, int batchSize, boolean ignoreNulls) { 315 Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 316 return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, (mapper, entity) -> mapper.update(entity, ignoreNulls))); 317 } 318 //endregion ===== 更新(改)操作 ===== 319 320 //region ===== 查询(查)操作 ===== 321 322 /** 323 * <p>根据数据主键查询一条数据。 324 * 325 * @param id 数据主键 326 * @return 查询结果数据 327 */ 328 default T getById(Serializable id) { 329 return getMapper().selectOneById(id); 330 } 331 332 /** 333 * <p>根据实体主键查询数据。 334 * 335 * @param entity 实体对象,必须包含有主键 336 * @return 查询结果数据 337 */ 338 default T getOneByEntityId(T entity) { 339 return getMapper().selectOneByEntityId(entity); 340 } 341 342 /** 343 * <p>根据实体主键查询数据。 344 * 345 * @param entity 实体对象,必须包含有主键 346 * @return 查询结果数据 347 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 348 */ 349 default Optional<T> getByEntityIdOpt(T entity) { 350 return Optional.ofNullable(getOneByEntityId(entity)); 351 } 352 353 /** 354 * <p>根据数据主键查询一条数据。 355 * 356 * @param id 数据主键 357 * @return 查询结果数据 358 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 359 */ 360 default Optional<T> getByIdOpt(Serializable id) { 361 return Optional.ofNullable(getById(id)); 362 } 363 364 /** 365 * <p>根据查询条件查询一条数据。 366 * 367 * @param query 查询条件 368 * @return 查询结果数据 369 */ 370 default T getOne(QueryWrapper query) { 371 return getMapper().selectOneByQuery(query); 372 } 373 374 /** 375 * <p>根据查询条件查询一条数据。 376 * 377 * @param query 查询条件 378 * @return 查询结果数据 379 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 380 */ 381 default Optional<T> getOneOpt(QueryWrapper query) { 382 return Optional.ofNullable(getOne(query)); 383 } 384 385 /** 386 * <p>根据查询条件查询一条数据,并通过 asType 进行接收。 387 * 388 * @param query 查询条件 389 * @param asType 接收的数据类型 390 * @return 查询结果数据 391 */ 392 default <R> R getOneAs(QueryWrapper query, Class<R> asType) { 393 return getMapper().selectOneByQueryAs(query, asType); 394 } 395 396 /** 397 * <p>根据查询条件查询一条数据。 398 * 399 * @param query 查询条件 400 * @param asType 接收的数据类型 401 * @return 查询结果数据 402 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 403 */ 404 default <R> Optional<R> getOneAsOpt(QueryWrapper query, Class<R> asType) { 405 return Optional.ofNullable(getOneAs(query, asType)); 406 } 407 408 /** 409 * <p>根据查询条件查询一条数据。 410 * 411 * @param condition 查询条件 412 * @return 查询结果数据 413 */ 414 default T getOne(QueryCondition condition) { 415 return getOne(query().where(condition).limit(1)); 416 } 417 418 /** 419 * <p>根据查询条件查询一条数据。 420 * 421 * @param condition 查询条件 422 * @return 查询结果数据 423 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 424 */ 425 default Optional<T> getOneOpt(QueryCondition condition) { 426 return Optional.ofNullable(getOne(condition)); 427 } 428 429 /** 430 * <p>查询结果集中第一列,且第一条数据。 431 * 432 * @param query 查询条件 433 * @return 数据值 434 */ 435 default Object getObj(QueryWrapper query) { 436 return getMapper().selectObjectByQuery(query); 437 } 438 439 /** 440 * <p>查询结果集中第一列,且第一条数据,并封装为 {@link Optional} 返回。 441 * 442 * @param query 查询条件 443 * @return 数据值 444 */ 445 default Optional<Object> getObjOpt(QueryWrapper query) { 446 return Optional.ofNullable(getObj(query)); 447 } 448 449 /** 450 * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 451 * 452 * @param query 查询条件 453 * @param asType 接收的数据类型 454 * @return 数据值 455 */ 456 default <R> R getObjAs(QueryWrapper query, Class<R> asType) { 457 return getMapper().selectObjectByQueryAs(query, asType); 458 } 459 460 /** 461 * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 462 * 等,封装为 {@link Optional} 返回。 463 * 464 * @param query 查询条件 465 * @param asType 接收的数据类型 466 * @return 数据值 467 */ 468 default <R> Optional<R> getObjAsOpt(QueryWrapper query, Class<R> asType) { 469 return Optional.ofNullable(getObjAs(query, asType)); 470 } 471 472 /** 473 * <p>查询结果集中第一列所有数据。 474 * 475 * @param query 查询条件 476 * @return 数据列表 477 */ 478 default List<Object> objList(QueryWrapper query) { 479 return getMapper().selectObjectListByQuery(query); 480 } 481 482 /** 483 * <p>查询结果集中第一列所有数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 484 * 485 * @param query 查询条件 486 * @param asType 接收的数据类型 487 * @return 数据列表 488 */ 489 default <R> List<R> objListAs(QueryWrapper query, Class<R> asType) { 490 return getMapper().selectObjectListByQueryAs(query, asType); 491 } 492 493 /** 494 * <p>查询所有数据。 495 * 496 * @return 所有数据 497 */ 498 default List<T> list() { 499 return list(query()); 500 } 501 502 /** 503 * <p>根据查询条件查询数据集合。 504 * 505 * @param query 查询条件 506 * @return 数据集合 507 */ 508 default List<T> list(QueryWrapper query) { 509 return getMapper().selectListByQuery(query); 510 } 511 512 /** 513 * <p>根据查询条件查询数据集合。 514 * 515 * @param condition 查询条件 516 * @return 数据集合 517 */ 518 default List<T> list(QueryCondition condition) { 519 return list(query().where(condition)); 520 } 521 522 /** 523 * <p>根据查询条件查询数据集合,并通过 asType 进行接收。 524 * 525 * @param query 查询条件 526 * @param asType 接收的数据类型 527 * @return 数据集合 528 */ 529 default <R> List<R> listAs(QueryWrapper query, Class<R> asType) { 530 return getMapper().selectListByQueryAs(query, asType); 531 } 532 533 /** 534 * <p>根据数据主键查询数据集合。 535 * 536 * @param ids 数据主键 537 * @return 数据集合 538 */ 539 default List<T> listByIds(Collection<? extends Serializable> ids) { 540 return getMapper().selectListByIds(ids); 541 } 542 543 /** 544 * <p>根据 {@link Map} 构建查询条件查询数据集合。 545 * 546 * @param query 查询条件 547 * @return 数据集合 548 */ 549 default List<T> listByMap(Map<String, Object> query) { 550 return list(query().where(query)); 551 } 552 //endregion ===== 查询(查)操作 ===== 553 554 //region ===== 数量查询操作 ===== 555 556 /** 557 * <p>根据查询条件判断数据是否存在。 558 * 559 * @param query 查询条件 560 * @return {@code true} 数据存在,{@code false} 数据不存在。 561 */ 562 default boolean exists(QueryWrapper query) { 563 return exists(CPI.getWhereQueryCondition(query)); 564 } 565 566 /** 567 * <p>根据查询条件判断数据是否存在。 568 * 569 * @param condition 查询条件 570 * @return {@code true} 数据存在,{@code false} 数据不存在。 571 */ 572 default boolean exists(QueryCondition condition) { 573 // 根据查询条件构建 SQL 语句 574 // SELECT 1 FROM table WHERE ... LIMIT 1 575 QueryWrapper queryWrapper = QueryMethods.selectOne() 576 .where(condition) 577 .limit(1); 578 // 获取数据集合,空集合:[] 不存在数据,有一个元素的集合:[1] 存在数据 579 List<Object> objects = getMapper().selectObjectListByQuery(queryWrapper); 580 // 判断是否存在数据 581 return CollectionUtil.isNotEmpty(objects); 582 } 583 584 /** 585 * <p>查询所有数据数量。 586 * 587 * @return 所有数据数量 588 */ 589 default long count() { 590 return count(query()); 591 } 592 593 /** 594 * <p>根据查询条件查询数据数量。 595 * 596 * @param query 查询条件 597 * @return 数据数量 598 */ 599 default long count(QueryWrapper query) { 600 return getMapper().selectCountByQuery(query); 601 } 602 603 /** 604 * <p>根据查询条件查询数据数量。 605 * 606 * @param condition 查询条件 607 * @return 数据数量 608 */ 609 default long count(QueryCondition condition) { 610 return count(query().where(condition)); 611 } 612 //endregion ===== 数量查询操作 ===== 613 614 //region ===== 分页查询操作 ===== 615 616 /** 617 * <p>分页查询所有数据。 618 * 619 * @param page 分页对象 620 * @return 分页对象 621 */ 622 default Page<T> page(Page<T> page) { 623 return page(page, query()); 624 } 625 626 /** 627 * <p>根据查询条件分页查询数据。 628 * 629 * @param page 分页对象 630 * @param query 查询条件 631 * @return 分页对象 632 */ 633 default Page<T> page(Page<T> page, QueryWrapper query) { 634 return pageAs(page, query, null); 635 } 636 637 /** 638 * <p>根据查询条件分页查询数据。 639 * 640 * @param page 分页对象 641 * @param condition 查询条件 642 * @return 分页对象 643 */ 644 default Page<T> page(Page<T> page, QueryCondition condition) { 645 return page(page, query().where(condition)); 646 } 647 648 /** 649 * <p>根据查询条件分页查询数据,并通过 asType 进行接收。 650 * 651 * @param page 分页对象 652 * @param query 查询条件 653 * @param asType 接收的数据类型 654 * @return 分页对象 655 */ 656 default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) { 657 return getMapper().paginateAs(page, query, asType); 658 } 659 //endregion ===== 分页查询操作 ===== 660 661 //region ===== 查询包装器操作 ===== 662 663 /** 664 * 默认 {@link QueryWrapper} 构建。 665 * 666 * @return {@link QueryWrapper} 对象 667 */ 668 default QueryWrapper query() { 669 return QueryWrapper.create(); 670 } 671 672 /** 673 * 链式查询。 674 * 675 * @return {@link QueryChain} 对象 676 */ 677 default QueryChain<T> queryChain() { 678 return QueryChain.of(getMapper()); 679 } 680 681 /** 682 * 链式更新。 683 * 684 * @return {@link UpdateChain} 对象 685 */ 686 default UpdateChain<T> updateChain() { 687 return UpdateChain.create(getMapper()); 688 } 689 //endregion ===== 查询包装器操作 ===== 690}