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)); 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 * <p>根据查询条件删除数据。 101 * 102 * @param query 查询条件 103 * @return {@code true} 删除成功,{@code false} 删除失败。 104 */ 105 default boolean remove(QueryWrapper query) { 106 return SqlUtil.toBool(getMapper().deleteByQuery(query)); 107 } 108 109 /** 110 * <p>根据查询条件删除数据。 111 * 112 * @param condition 查询条件 113 * @return {@code true} 删除成功,{@code false} 删除失败。 114 */ 115 default boolean remove(QueryCondition condition) { 116 return remove(query().where(condition)); 117 } 118 119 /** 120 * <p>根据数据主键删除数据。 121 * 122 * @param id 数据主键 123 * @return {@code true} 删除成功,{@code false} 删除失败。 124 */ 125 default boolean removeById(Serializable id) { 126 return SqlUtil.toBool(getMapper().deleteById(id)); 127 } 128 129 /** 130 * <p>根据数据主键批量删除数据。 131 * 132 * @param ids 数据主键 133 * @return {@code true} 删除成功,{@code false} 删除失败。 134 */ 135 default boolean removeByIds(Collection<? extends Serializable> ids) { 136 if (CollectionUtil.isEmpty(ids)) { 137 return false; 138 } 139 return SqlUtil.toBool(getMapper().deleteBatchByIds(ids)); 140 } 141 142 // ===== 更新(改)操作 ===== 143 144 /** 145 * <p>根据 {@link Map} 构建查询条件删除数据。 146 * 147 * @param query 查询条件 148 * @return {@code true} 删除成功,{@code false} 删除失败。 149 */ 150 default boolean removeByMap(Map<String, Object> query) { 151 // 防止全表删除 152 if (query == null || query.isEmpty()) { 153 throw FlexExceptions.wrap("deleteByMap is not allow empty map."); 154 } 155 return remove(query().where(query)); 156 } 157 158 /** 159 * <p>根据数据主键更新数据。 160 * 161 * @param entity 实体类对象 162 * @return {@code true} 更新成功,{@code false} 更新失败。 163 * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 164 */ 165 default boolean updateById(T entity) { 166 return updateById(entity, true); 167 } 168 169 /** 170 * 根据主键更新数据 171 * 172 * @param entity 实体对象 173 * @param ignoreNulls 是否忽略 null 值 174 * @return {@code true} 更新成功,{@code false} 更新失败。 175 */ 176 default boolean updateById(T entity, boolean ignoreNulls) { 177 return SqlUtil.toBool(getMapper().update(entity, ignoreNulls)); 178 } 179 180 /** 181 * <p>根据 {@link Map} 构建查询条件更新数据。 182 * 183 * @param entity 实体类对象 184 * @param query 查询条件 185 * @return {@code true} 更新成功,{@code false} 更新失败。 186 */ 187 default boolean update(T entity, Map<String, Object> query) { 188 return update(entity, query().where(query)); 189 } 190 191 /** 192 * <p>根据查询条件更新数据。 193 * 194 * @param entity 实体类对象 195 * @param query 查询条件 196 * @return {@code true} 更新成功,{@code false} 更新失败。 197 */ 198 default boolean update(T entity, QueryWrapper query) { 199 return SqlUtil.toBool(getMapper().updateByQuery(entity, query)); 200 } 201 202 /** 203 * <p>根据查询条件更新数据。 204 * 205 * @param entity 实体类对象 206 * @param condition 查询条件 207 * @return {@code true} 更新成功,{@code false} 更新失败。 208 */ 209 default boolean update(T entity, QueryCondition condition) { 210 return update(entity, query().where(condition)); 211 } 212 213 /** 214 * <p>根据数据主键批量更新数据 215 * 216 * @param entities 实体类对象集合 217 * @return boolean {@code true} 更新成功,{@code false} 更新失败。 218 */ 219 default boolean updateBatch(Collection<T> entities) { 220 return updateBatch(entities, DEFAULT_BATCH_SIZE); 221 } 222 223 /** 224 * <p>根据数据主键批量更新数据 225 * 226 * @param entities 实体类对象集合 227 * @param batchSize 每批次更新数量 228 * @return {@code true} 更新成功,{@code false} 更新失败。 229 */ 230 default boolean updateBatch(Collection<T> entities, int batchSize) { 231 return Db.tx(() -> { 232 final List<T> entityList = CollectionUtil.toList(entities); 233 // BaseMapper 是经过 Mybatis 动态代理处理过的对象,需要获取原始 BaseMapper 类型 234 final Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass()); 235 return SqlUtil.toBool(Arrays.stream(Db.executeBatch(entityList.size(), batchSize, usefulClass, (mapper, index) -> mapper.update(entityList.get(index)))).sum()); 236 }); 237 } 238 239 240 // ===== 查询(查)操作 ===== 241 242 /** 243 * <p>根据数据主键查询一条数据。 244 * 245 * @param id 数据主键 246 * @return 查询结果数据 247 */ 248 default T getById(Serializable id) { 249 return getMapper().selectOneById(id); 250 } 251 252 /** 253 * <p>根据数据主键查询一条数据。 254 * 255 * @param id 数据主键 256 * @return 查询结果数据 257 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 258 */ 259 default Optional<T> getByIdOpt(Serializable id) { 260 return Optional.ofNullable(getById(id)); 261 } 262 263 /** 264 * <p>根据查询条件查询一条数据。 265 * 266 * @param query 查询条件 267 * @return 查询结果数据 268 */ 269 default T getOne(QueryWrapper query) { 270 return getMapper().selectOneByQuery(query); 271 } 272 273 /** 274 * <p>根据查询条件查询一条数据。 275 * 276 * @param query 查询条件 277 * @return 查询结果数据 278 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 279 */ 280 default Optional<T> getOneOpt(QueryWrapper query) { 281 return Optional.ofNullable(getOne(query)); 282 } 283 284 /** 285 * <p>根据查询条件查询一条数据,并通过 asType 进行接收。 286 * 287 * @param query 查询条件 288 * @param asType 接收的数据类型 289 * @return 查询结果数据 290 */ 291 default <R> R getOneAs(QueryWrapper query, Class<R> asType) { 292 return getMapper().selectOneByQueryAs(query, asType); 293 } 294 295 /** 296 * <p>根据查询条件查询一条数据。 297 * 298 * @param query 查询条件 299 * @param asType 接收的数据类型 300 * @return 查询结果数据 301 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 302 */ 303 default <R> Optional<R> getOneAsOpt(QueryWrapper query, Class<R> asType) { 304 return Optional.ofNullable(getOneAs(query, asType)); 305 } 306 307 /** 308 * <p>根据查询条件查询一条数据。 309 * 310 * @param condition 查询条件 311 * @return 查询结果数据 312 */ 313 default T getOne(QueryCondition condition) { 314 return getOne(query().where(condition)); 315 } 316 317 /** 318 * <p>根据查询条件查询一条数据。 319 * 320 * @param condition 查询条件 321 * @return 查询结果数据 322 * @apiNote 该方法会将查询结果封装为 {@link Optional} 类进行返回,方便链式操作。 323 */ 324 default Optional<T> getOneOpt(QueryCondition condition) { 325 return Optional.ofNullable(getOne(condition)); 326 } 327 328 /** 329 * <p>查询所有数据。 330 * 331 * @return 所有数据 332 */ 333 default List<T> list() { 334 return list(query()); 335 } 336 337 /** 338 * <p>根据查询条件查询数据集合。 339 * 340 * @param query 查询条件 341 * @return 数据集合 342 */ 343 default List<T> list(QueryWrapper query) { 344 return getMapper().selectListByQuery(query); 345 } 346 347 /** 348 * <p>根据查询条件查询数据集合。 349 * 350 * @param condition 查询条件 351 * @return 数据集合 352 */ 353 default List<T> list(QueryCondition condition) { 354 return list(query().where(condition)); 355 } 356 357 /** 358 * <p>根据查询条件查询数据集合,并通过 asType 进行接收。 359 * 360 * @param query 查询条件 361 * @param asType 接收的数据类型 362 * @return 数据集合 363 */ 364 default <R> List<R> listAs(QueryWrapper query, Class<R> asType) { 365 return getMapper().selectListByQueryAs(query, asType); 366 } 367 368 /** 369 * <p>根据数据主键查询数据集合。 370 * 371 * @param ids 数据主键 372 * @return 数据集合 373 */ 374 default List<T> listByIds(Collection<? extends Serializable> ids) { 375 return getMapper().selectListByIds(ids); 376 } 377 378 /** 379 * <p>根据 {@link Map} 构建查询条件查询数据集合。 380 * 381 * @param query 查询条件 382 * @return 数据集合 383 */ 384 default List<T> listByMap(Map<String, Object> query) { 385 return list(query().where(query)); 386 } 387 388 // ===== 数量查询操作 ===== 389 390 /** 391 * <p>根据查询条件判断数据是否存在。 392 * 393 * @param query 查询条件 394 * @return {@code true} 数据存在,{@code false} 数据不存在。 395 */ 396 default boolean exists(QueryWrapper query) { 397 return SqlUtil.toBool(count(query)); 398 } 399 400 /** 401 * <p>根据查询条件判断数据是否存在。 402 * 403 * @param condition 查询条件 404 * @return {@code true} 数据存在,{@code false} 数据不存在。 405 */ 406 default boolean exists(QueryCondition condition) { 407 return SqlUtil.toBool(count(condition)); 408 } 409 410 /** 411 * <p>查询所有数据数量。 412 * 413 * @return 所有数据数量 414 */ 415 default long count() { 416 return count(query()); 417 } 418 419 /** 420 * <p>根据查询条件查询数据数量。 421 * 422 * @param query 查询条件 423 * @return 数据数量 424 */ 425 default long count(QueryWrapper query) { 426 return getMapper().selectCountByQuery(query); 427 } 428 429 /** 430 * <p>根据查询条件查询数据数量。 431 * 432 * @param condition 查询条件 433 * @return 数据数量 434 */ 435 default long count(QueryCondition condition) { 436 return count(query().where(condition)); 437 } 438 439 // ===== 分页查询操作 ===== 440 441 /** 442 * <p>分页查询所有数据。 443 * 444 * @param page 分页对象 445 * @return 分页对象 446 */ 447 default Page<T> page(Page<T> page) { 448 return page(page, query()); 449 } 450 451 /** 452 * <p>根据查询条件分页查询数据。 453 * 454 * @param page 分页对象 455 * @param query 查询条件 456 * @return 分页对象 457 */ 458 default Page<T> page(Page<T> page, QueryWrapper query) { 459 return pageAs(page, query, null); 460 } 461 462 /** 463 * <p>根据查询条件分页查询数据。 464 * 465 * @param page 分页对象 466 * @param condition 查询条件 467 * @return 分页对象 468 */ 469 default Page<T> page(Page<T> page, QueryCondition condition) { 470 return page(page, query().where(condition)); 471 } 472 473 /** 474 * <p>根据查询条件分页查询数据,并通过 asType 进行接收。 475 * 476 * @param page 分页对象 477 * @param query 查询条件 478 * @param asType 接收的数据类型 479 * @return 分页对象 480 */ 481 default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) { 482 return getMapper().paginateAs(page, query, asType); 483 } 484 485 default QueryWrapper query() { 486 return QueryWrapper.create(); 487 } 488 489}