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