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 * <p>根据数据主键批量更新数据 274 * 275 * @param entities 实体类对象集合 276 * @param batchSize 每批次更新数量 277 * @return {@code true} 更新成功,{@code false} 更新失败。 278 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 279 */ 280 default boolean updateBatch(Collection<T> entities, int batchSize) { 281 Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 282 return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::update)); 283 } 284 285 // ===== 查询(查)操作 ===== 286 287 /** 288 * <p>根据数据主键查询一条数据。 289 * 290 * @param id 数据主键 291 * @return 查询结果数据 292 */ 293 default T getById(Serializable id) { 294 return getMapper().selectOneById(id); 295 } 296 297 /** 298 * <p>根据实体主键查询数据。 299 * 300 * @param entity 实体对象,必须包含有主键 301 * @return 查询结果数据 302 */ 303 default T getOneByEntityId(T entity) { 304 return getMapper().selectOneByEntityId(entity); 305 } 306 307 /** 308 * <p>根据实体主键查询数据。 309 * 310 * @param entity 实体对象,必须包含有主键 311 * @return 查询结果数据 312 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 313 */ 314 default Optional<T> getByEntityIdOpt(T entity) { 315 return Optional.ofNullable(getOneByEntityId(entity)); 316 } 317 /** 318 * <p>根据数据主键查询一条数据。 319 * 320 * @param id 数据主键 321 * @return 查询结果数据 322 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 323 */ 324 default Optional<T> getByIdOpt(Serializable id) { 325 return Optional.ofNullable(getById(id)); 326 } 327 328 /** 329 * <p>根据查询条件查询一条数据。 330 * 331 * @param query 查询条件 332 * @return 查询结果数据 333 */ 334 default T getOne(QueryWrapper query) { 335 return getMapper().selectOneByQuery(query); 336 } 337 338 /** 339 * <p>根据查询条件查询一条数据。 340 * 341 * @param query 查询条件 342 * @return 查询结果数据 343 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 344 */ 345 default Optional<T> getOneOpt(QueryWrapper query) { 346 return Optional.ofNullable(getOne(query)); 347 } 348 349 /** 350 * <p>根据查询条件查询一条数据,并通过 asType 进行接收。 351 * 352 * @param query 查询条件 353 * @param asType 接收的数据类型 354 * @return 查询结果数据 355 */ 356 default <R> R getOneAs(QueryWrapper query, Class<R> asType) { 357 return getMapper().selectOneByQueryAs(query, asType); 358 } 359 360 /** 361 * <p>根据查询条件查询一条数据。 362 * 363 * @param query 查询条件 364 * @param asType 接收的数据类型 365 * @return 查询结果数据 366 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 367 */ 368 default <R> Optional<R> getOneAsOpt(QueryWrapper query, Class<R> asType) { 369 return Optional.ofNullable(getOneAs(query, asType)); 370 } 371 372 /** 373 * <p>根据查询条件查询一条数据。 374 * 375 * @param condition 查询条件 376 * @return 查询结果数据 377 */ 378 default T getOne(QueryCondition condition) { 379 return getOne(query().where(condition).limit(1)); 380 } 381 382 /** 383 * <p>根据查询条件查询一条数据。 384 * 385 * @param condition 查询条件 386 * @return 查询结果数据 387 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 388 */ 389 default Optional<T> getOneOpt(QueryCondition condition) { 390 return Optional.ofNullable(getOne(condition)); 391 } 392 393 /** 394 * <p>查询结果集中第一列,且第一条数据。 395 * 396 * @param query 查询条件 397 * @return 数据值 398 */ 399 default Object getObj(QueryWrapper query) { 400 return getMapper().selectObjectByQuery(query); 401 } 402 403 /** 404 * <p>查询结果集中第一列,且第一条数据,并封装为 {@link Optional} 返回。 405 * 406 * @param query 查询条件 407 * @return 数据值 408 */ 409 default Optional<Object> getObjOpt(QueryWrapper query) { 410 return Optional.ofNullable(getObj(query)); 411 } 412 413 /** 414 * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 415 * 416 * @param query 查询条件 417 * @param asType 接收的数据类型 418 * @return 数据值 419 */ 420 default <R> R getObjAs(QueryWrapper query, Class<R> asType) { 421 return getMapper().selectObjectByQueryAs(query, asType); 422 } 423 424 /** 425 * <p>查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 426 * 等,封装为 {@link Optional} 返回。 427 * 428 * @param query 查询条件 429 * @param asType 接收的数据类型 430 * @return 数据值 431 */ 432 default <R> Optional<R> getObjAsOpt(QueryWrapper query, Class<R> asType) { 433 return Optional.ofNullable(getObjAs(query, asType)); 434 } 435 436 /** 437 * <p>查询结果集中第一列所有数据。 438 * 439 * @param query 查询条件 440 * @return 数据列表 441 */ 442 default List<Object> objList(QueryWrapper query) { 443 return getMapper().selectObjectListByQuery(query); 444 } 445 446 /** 447 * <p>查询结果集中第一列所有数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 448 * 449 * @param query 查询条件 450 * @param asType 接收的数据类型 451 * @return 数据列表 452 */ 453 default <R> List<R> objListAs(QueryWrapper query, Class<R> asType) { 454 return getMapper().selectObjectListByQueryAs(query, asType); 455 } 456 457 /** 458 * <p>查询所有数据。 459 * 460 * @return 所有数据 461 */ 462 default List<T> list() { 463 return list(query()); 464 } 465 466 /** 467 * <p>根据查询条件查询数据集合。 468 * 469 * @param query 查询条件 470 * @return 数据集合 471 */ 472 default List<T> list(QueryWrapper query) { 473 return getMapper().selectListByQuery(query); 474 } 475 476 /** 477 * <p>根据查询条件查询数据集合。 478 * 479 * @param condition 查询条件 480 * @return 数据集合 481 */ 482 default List<T> list(QueryCondition condition) { 483 return list(query().where(condition)); 484 } 485 486 /** 487 * <p>根据查询条件查询数据集合,并通过 asType 进行接收。 488 * 489 * @param query 查询条件 490 * @param asType 接收的数据类型 491 * @return 数据集合 492 */ 493 default <R> List<R> listAs(QueryWrapper query, Class<R> asType) { 494 return getMapper().selectListByQueryAs(query, asType); 495 } 496 497 /** 498 * <p>根据数据主键查询数据集合。 499 * 500 * @param ids 数据主键 501 * @return 数据集合 502 */ 503 default List<T> listByIds(Collection<? extends Serializable> ids) { 504 return getMapper().selectListByIds(ids); 505 } 506 507 /** 508 * <p>根据 {@link Map} 构建查询条件查询数据集合。 509 * 510 * @param query 查询条件 511 * @return 数据集合 512 */ 513 default List<T> listByMap(Map<String, Object> query) { 514 return list(query().where(query)); 515 } 516 517 // ===== 数量查询操作 ===== 518 519 /** 520 * <p>根据查询条件判断数据是否存在。 521 * 522 * @param query 查询条件 523 * @return {@code true} 数据存在,{@code false} 数据不存在。 524 */ 525 default boolean exists(QueryWrapper query) { 526 return exists(CPI.getWhereQueryCondition(query)); 527 } 528 529 /** 530 * <p>根据查询条件判断数据是否存在。 531 * 532 * @param condition 查询条件 533 * @return {@code true} 数据存在,{@code false} 数据不存在。 534 */ 535 default boolean exists(QueryCondition condition) { 536 // 根据查询条件构建 SQL 语句 537 // SELECT 1 FROM table WHERE ... LIMIT 1 538 QueryWrapper queryWrapper = QueryMethods.selectOne() 539 .where(condition) 540 .limit(1); 541 // 获取数据集合,空集合:[] 不存在数据,有一个元素的集合:[1] 存在数据 542 List<Object> objects = getMapper().selectObjectListByQuery(queryWrapper); 543 // 判断是否存在数据 544 return CollectionUtil.isNotEmpty(objects); 545 } 546 547 /** 548 * <p>查询所有数据数量。 549 * 550 * @return 所有数据数量 551 */ 552 default long count() { 553 return count(query()); 554 } 555 556 /** 557 * <p>根据查询条件查询数据数量。 558 * 559 * @param query 查询条件 560 * @return 数据数量 561 */ 562 default long count(QueryWrapper query) { 563 return getMapper().selectCountByQuery(query); 564 } 565 566 /** 567 * <p>根据查询条件查询数据数量。 568 * 569 * @param condition 查询条件 570 * @return 数据数量 571 */ 572 default long count(QueryCondition condition) { 573 return count(query().where(condition)); 574 } 575 576 // ===== 分页查询操作 ===== 577 578 /** 579 * <p>分页查询所有数据。 580 * 581 * @param page 分页对象 582 * @return 分页对象 583 */ 584 default Page<T> page(Page<T> page) { 585 return page(page, query()); 586 } 587 588 /** 589 * <p>根据查询条件分页查询数据。 590 * 591 * @param page 分页对象 592 * @param query 查询条件 593 * @return 分页对象 594 */ 595 default Page<T> page(Page<T> page, QueryWrapper query) { 596 return pageAs(page, query, null); 597 } 598 599 /** 600 * <p>根据查询条件分页查询数据。 601 * 602 * @param page 分页对象 603 * @param condition 查询条件 604 * @return 分页对象 605 */ 606 default Page<T> page(Page<T> page, QueryCondition condition) { 607 return page(page, query().where(condition)); 608 } 609 610 /** 611 * <p>根据查询条件分页查询数据,并通过 asType 进行接收。 612 * 613 * @param page 分页对象 614 * @param query 查询条件 615 * @param asType 接收的数据类型 616 * @return 分页对象 617 */ 618 default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) { 619 return getMapper().paginateAs(page, query, asType); 620 } 621 622 // ===== 查询包装器操作 ===== 623 624 /** 625 * 默认 {@link QueryWrapper} 构建。 626 * 627 * @return {@link QueryWrapper} 对象 628 */ 629 default QueryWrapper query() { 630 return QueryWrapper.create(); 631 } 632 633 /** 634 * 链式查询。 635 * 636 * @return {@link QueryChain} 对象 637 */ 638 default QueryChain<T> queryChain() { 639 return QueryChain.of(getMapper()); 640 } 641 642 /** 643 * 链式更新。 644 * 645 * @return {@link UpdateChain} 对象 646 */ 647 default UpdateChain<T> updateChain() { 648 return UpdateChain.create(getMapper()); 649 } 650 651}