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.QueryCondition; 022import com.mybatisflex.core.query.QueryWrapper; 023import com.mybatisflex.core.row.Db; 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.*; 030 031 032/** 033 * 由 Mybatis-Flex 提供的顶级增强 Service 接口。 034 * 035 * @param <T> 实体类(Entity)类型 036 * @author 王帅 037 * @since 2023-05-01 038 */ 039@SuppressWarnings({"unused", "unchecked"}) 040public interface IService<T> { 041 042 int DEFAULT_BATCH_SIZE = 1000; 043 044 // ===== 保存(增)操作 ===== 045 046 /** 047 * <p>获取对应实体类(Entity)的基础映射类(BaseMapper)。 048 * 049 * @return 基础映射类(BaseMapper) 050 */ 051 BaseMapper<T> getMapper(); 052 053 /** 054 * <p>保存实体类对象数据。 055 * 056 * @param entity 实体类对象 057 * @return {@code true} 保存成功,{@code false} 保存失败。 058 * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略 059 * {@code null} 字段的数据,使数据库配置的默认值生效。 060 */ 061 default boolean save(T entity) { 062 return SqlUtil.toBool(getMapper().insertSelective(entity)); 063 } 064 065 /** 066 * <p>保存或者更新实体类对象数据。 067 * 068 * @param entity 实体类对象 069 * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。 070 * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据。 071 */ 072 default boolean saveOrUpdate(T entity) { 073 return SqlUtil.toBool(getMapper().insertOrUpdate(entity, true)); 074 } 075 076 /** 077 * <p>批量保存实体类对象数据。 078 * 079 * @param entities 实体类对象 080 * @return {@code true} 保存成功,{@code false} 保存失败。 081 */ 082 default boolean saveBatch(Collection<T> entities) { 083 return saveBatch(entities, DEFAULT_BATCH_SIZE); 084 } 085 086 // ===== 删除(删)操作 ===== 087 088 /** 089 * <p>批量保存实体类对象数据。 090 * 091 * @param entities 实体类对象 092 * @param batchSize 每次保存切分的数量 093 * @return {@code true} 保存成功,{@code false} 保存失败。 094 */ 095 default boolean saveBatch(Collection<T> entities, int batchSize) { 096 return SqlUtil.toBool(getMapper().insertBatch(CollectionUtil.toList(entities), batchSize)); 097 } 098 099 100 /** 101 * <p>批量保存实体类对象数据。 102 * 103 * @param entities 实体类对象 104 * @return {@code true} 保存成功,{@code false} 保存失败。 105 */ 106 default boolean saveBatchSelective(Collection<T> entities) { 107 return saveBatchSelective(entities, DEFAULT_BATCH_SIZE); 108 } 109 110 // ===== 删除(删)操作 ===== 111 112 /** 113 * <p>批量保存实体类对象数据。 114 * 115 * @param entities 实体类对象 116 * @param batchSize 每次保存切分的数量 117 * @return {@code true} 保存成功,{@code false} 保存失败。 118 */ 119 default boolean saveBatchSelective(Collection<T> entities, int batchSize) { 120 List<T> entityList = CollectionUtil.toList(entities); 121 Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 122 return SqlUtil.toBool( 123 Db.executeBatch(entities.size(), batchSize, usefulClass, (mapper, integer) -> mapper.insertSelective(entityList.get(integer))) 124 ); 125 } 126 127 128 /** 129 * <p>根据查询条件删除数据。 130 * 131 * @param query 查询条件 132 * @return {@code true} 删除成功,{@code false} 删除失败。 133 */ 134 default boolean remove(QueryWrapper query) { 135 return SqlUtil.toBool(getMapper().deleteByQuery(query)); 136 } 137 138 /** 139 * <p>根据查询条件删除数据。 140 * 141 * @param condition 查询条件 142 * @return {@code true} 删除成功,{@code false} 删除失败。 143 */ 144 default boolean remove(QueryCondition condition) { 145 return remove(query().where(condition)); 146 } 147 148 /** 149 * <p>根据数据主键删除数据。 150 * 151 * @param id 数据主键 152 * @return {@code true} 删除成功,{@code false} 删除失败。 153 */ 154 default boolean removeById(Serializable id) { 155 return SqlUtil.toBool(getMapper().deleteById(id)); 156 } 157 158 /** 159 * <p>根据数据主键批量删除数据。 160 * 161 * @param ids 数据主键 162 * @return {@code true} 删除成功,{@code false} 删除失败。 163 */ 164 default boolean removeByIds(Collection<? extends Serializable> ids) { 165 if (CollectionUtil.isEmpty(ids)) { 166 return false; 167 } 168 return SqlUtil.toBool(getMapper().deleteBatchByIds(ids)); 169 } 170 171 // ===== 更新(改)操作 ===== 172 173 /** 174 * <p>根据 {@link Map} 构建查询条件删除数据。 175 * 176 * @param query 查询条件 177 * @return {@code true} 删除成功,{@code false} 删除失败。 178 */ 179 default boolean removeByMap(Map<String, Object> query) { 180 // 防止全表删除 181 if (query == null || query.isEmpty()) { 182 throw FlexExceptions.wrap("deleteByMap is not allow empty map."); 183 } 184 return remove(query().where(query)); 185 } 186 187 /** 188 * <p>根据数据主键更新数据。 189 * 190 * @param entity 实体类对象 191 * @return {@code true} 更新成功,{@code false} 更新失败。 192 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 193 */ 194 default boolean updateById(T entity) { 195 return updateById(entity, true); 196 } 197 198 /** 199 * 根据主键更新数据 200 * 201 * @param entity 实体对象 202 * @param ignoreNulls 是否忽略 null 值 203 * @return {@code true} 更新成功,{@code false} 更新失败。 204 */ 205 default boolean updateById(T entity, boolean ignoreNulls) { 206 return SqlUtil.toBool(getMapper().update(entity, ignoreNulls)); 207 } 208 209 /** 210 * <p>根据 {@link Map} 构建查询条件更新数据。 211 * 212 * @param entity 实体类对象 213 * @param query 查询条件 214 * @return {@code true} 更新成功,{@code false} 更新失败。 215 */ 216 default boolean update(T entity, Map<String, Object> query) { 217 return update(entity, query().where(query)); 218 } 219 220 /** 221 * <p>根据查询条件更新数据。 222 * 223 * @param entity 实体类对象 224 * @param query 查询条件 225 * @return {@code true} 更新成功,{@code false} 更新失败。 226 */ 227 default boolean update(T entity, QueryWrapper query) { 228 return SqlUtil.toBool(getMapper().updateByQuery(entity, query)); 229 } 230 231 /** 232 * <p>根据查询条件更新数据。 233 * 234 * @param entity 实体类对象 235 * @param condition 查询条件 236 * @return {@code true} 更新成功,{@code false} 更新失败。 237 */ 238 default boolean update(T entity, QueryCondition condition) { 239 return update(entity, query().where(condition)); 240 } 241 242 /** 243 * <p>根据数据主键批量更新数据 244 * 245 * @param entities 实体类对象集合 246 * @return boolean {@code true} 更新成功,{@code false} 更新失败。 247 */ 248 default boolean updateBatch(Collection<T> entities) { 249 return updateBatch(entities, DEFAULT_BATCH_SIZE); 250 } 251 252 /** 253 * <p>根据数据主键批量更新数据 254 * 255 * @param entities 实体类对象集合 256 * @param batchSize 每批次更新数量 257 * @return {@code true} 更新成功,{@code false} 更新失败。 258 */ 259 default boolean updateBatch(Collection<T> entities, int batchSize) { 260 List<T> entityList = CollectionUtil.toList(entities); 261 // BaseMapper 是经过 Mybatis 动态代理处理过的对象,需要获取原始 BaseMapper 类型 262 Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 263 return SqlUtil.toBool( 264 Db.executeBatch( 265 entityList.size() 266 , batchSize 267 , usefulClass 268 , (mapper, index) -> mapper.update(entityList.get(index))) 269 ); 270 } 271 272 273 // ===== 查询(查)操作 ===== 274 275 /** 276 * <p>根据数据主键查询一条数据。 277 * 278 * @param id 数据主键 279 * @return 查询结果数据 280 */ 281 default T getById(Serializable id) { 282 return getMapper().selectOneById(id); 283 } 284 285 /** 286 * <p>根据数据主键查询一条数据。 287 * 288 * @param id 数据主键 289 * @return 查询结果数据 290 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 291 */ 292 default Optional<T> getByIdOpt(Serializable id) { 293 return Optional.ofNullable(getById(id)); 294 } 295 296 /** 297 * <p>根据查询条件查询一条数据。 298 * 299 * @param query 查询条件 300 * @return 查询结果数据 301 */ 302 default T getOne(QueryWrapper query) { 303 return getMapper().selectOneByQuery(query); 304 } 305 306 /** 307 * <p>根据查询条件查询一条数据。 308 * 309 * @param query 查询条件 310 * @return 查询结果数据 311 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 312 */ 313 default Optional<T> getOneOpt(QueryWrapper query) { 314 return Optional.ofNullable(getOne(query)); 315 } 316 317 /** 318 * <p>根据查询条件查询一条数据,并通过 asType 进行接收。 319 * 320 * @param query 查询条件 321 * @param asType 接收的数据类型 322 * @return 查询结果数据 323 */ 324 default <R> R getOneAs(QueryWrapper query, Class<R> asType) { 325 return getMapper().selectOneByQueryAs(query, asType); 326 } 327 328 /** 329 * <p>根据查询条件查询一条数据。 330 * 331 * @param query 查询条件 332 * @param asType 接收的数据类型 333 * @return 查询结果数据 334 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 335 */ 336 default <R> Optional<R> getOneAsOpt(QueryWrapper query, Class<R> asType) { 337 return Optional.ofNullable(getOneAs(query, asType)); 338 } 339 340 /** 341 * <p>根据查询条件查询一条数据。 342 * 343 * @param condition 查询条件 344 * @return 查询结果数据 345 */ 346 default T getOne(QueryCondition condition) { 347 return getOne(query().where(condition)); 348 } 349 350 /** 351 * <p>根据查询条件查询一条数据。 352 * 353 * @param condition 查询条件 354 * @return 查询结果数据 355 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 356 */ 357 default Optional<T> getOneOpt(QueryCondition condition) { 358 return Optional.ofNullable(getOne(condition)); 359 } 360 361 /** 362 * <p>查询所有数据。 363 * 364 * @return 所有数据 365 */ 366 default List<T> list() { 367 return list(query()); 368 } 369 370 /** 371 * <p>根据查询条件查询数据集合。 372 * 373 * @param query 查询条件 374 * @return 数据集合 375 */ 376 default List<T> list(QueryWrapper query) { 377 return getMapper().selectListByQuery(query); 378 } 379 380 /** 381 * <p>根据查询条件查询数据集合。 382 * 383 * @param condition 查询条件 384 * @return 数据集合 385 */ 386 default List<T> list(QueryCondition condition) { 387 return list(query().where(condition)); 388 } 389 390 /** 391 * <p>根据查询条件查询数据集合,并通过 asType 进行接收。 392 * 393 * @param query 查询条件 394 * @param asType 接收的数据类型 395 * @return 数据集合 396 */ 397 default <R> List<R> listAs(QueryWrapper query, Class<R> asType) { 398 return getMapper().selectListByQueryAs(query, asType); 399 } 400 401 /** 402 * <p>根据数据主键查询数据集合。 403 * 404 * @param ids 数据主键 405 * @return 数据集合 406 */ 407 default List<T> listByIds(Collection<? extends Serializable> ids) { 408 return getMapper().selectListByIds(ids); 409 } 410 411 /** 412 * <p>根据 {@link Map} 构建查询条件查询数据集合。 413 * 414 * @param query 查询条件 415 * @return 数据集合 416 */ 417 default List<T> listByMap(Map<String, Object> query) { 418 return list(query().where(query)); 419 } 420 421 // ===== 数量查询操作 ===== 422 423 /** 424 * <p>根据查询条件判断数据是否存在。 425 * 426 * @param query 查询条件 427 * @return {@code true} 数据存在,{@code false} 数据不存在。 428 */ 429 default boolean exists(QueryWrapper query) { 430 return SqlUtil.toBool(count(query)); 431 } 432 433 /** 434 * <p>根据查询条件判断数据是否存在。 435 * 436 * @param condition 查询条件 437 * @return {@code true} 数据存在,{@code false} 数据不存在。 438 */ 439 default boolean exists(QueryCondition condition) { 440 return SqlUtil.toBool(count(condition)); 441 } 442 443 /** 444 * <p>查询所有数据数量。 445 * 446 * @return 所有数据数量 447 */ 448 default long count() { 449 return count(query()); 450 } 451 452 /** 453 * <p>根据查询条件查询数据数量。 454 * 455 * @param query 查询条件 456 * @return 数据数量 457 */ 458 default long count(QueryWrapper query) { 459 return getMapper().selectCountByQuery(query); 460 } 461 462 /** 463 * <p>根据查询条件查询数据数量。 464 * 465 * @param condition 查询条件 466 * @return 数据数量 467 */ 468 default long count(QueryCondition condition) { 469 return count(query().where(condition)); 470 } 471 472 // ===== 分页查询操作 ===== 473 474 /** 475 * <p>分页查询所有数据。 476 * 477 * @param page 分页对象 478 * @return 分页对象 479 */ 480 default Page<T> page(Page<T> page) { 481 return page(page, query()); 482 } 483 484 /** 485 * <p>根据查询条件分页查询数据。 486 * 487 * @param page 分页对象 488 * @param query 查询条件 489 * @return 分页对象 490 */ 491 default Page<T> page(Page<T> page, QueryWrapper query) { 492 return pageAs(page, query, null); 493 } 494 495 /** 496 * <p>根据查询条件分页查询数据。 497 * 498 * @param page 分页对象 499 * @param condition 查询条件 500 * @return 分页对象 501 */ 502 default Page<T> page(Page<T> page, QueryCondition condition) { 503 return page(page, query().where(condition)); 504 } 505 506 /** 507 * <p>根据查询条件分页查询数据,并通过 asType 进行接收。 508 * 509 * @param page 分页对象 510 * @param query 查询条件 511 * @param asType 接收的数据类型 512 * @return 分页对象 513 */ 514 default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) { 515 return getMapper().paginateAs(page, query, asType); 516 } 517 518 default QueryWrapper query() { 519 return QueryWrapper.create(); 520 } 521 522}