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; 017 018import com.mybatisflex.core.exception.FlexExceptions; 019import com.mybatisflex.core.paginate.Page; 020import com.mybatisflex.core.provider.EntitySqlProvider; 021import com.mybatisflex.core.query.QueryColumn; 022import com.mybatisflex.core.query.QueryCondition; 023import com.mybatisflex.core.query.QueryWrapper; 024import com.mybatisflex.core.query.CPI; 025import com.mybatisflex.core.table.TableInfo; 026import com.mybatisflex.core.table.TableInfoFactory; 027import com.mybatisflex.core.util.ObjectUtil; 028import org.apache.ibatis.annotations.*; 029import org.apache.ibatis.builder.annotation.ProviderContext; 030 031import java.io.Serializable; 032import java.util.Collection; 033import java.util.List; 034import java.util.Map; 035 036public interface BaseMapper<T> { 037 038 /** 039 * 插入 entity 数据 040 * 041 * @param entity 实体类 042 * @return 返回影响的行数 043 */ 044 default int insert(T entity){ 045 return insert(entity,false); 046 } 047 048 049 /** 050 * 插入 entity 数据,但是忽略 null 的数据,只对有值的内容进行插入 051 * 这样的好处是数据库已经配置了一些默认值,这些默认值才会生效 052 * 053 * @param entity 实体类 054 * @return 返回影响的行数 055 */ 056 default int insertSelective(T entity){ 057 return insert(entity,true); 058 } 059 060 061 062 /** 063 * 插入 entity 数据 064 * 065 * @param entity 实体类 066 * @return 返回影响的行数 067 * @see com.mybatisflex.core.provider.EntitySqlProvider#insert(Map, ProviderContext) 068 */ 069 @InsertProvider(type = EntitySqlProvider.class, method = "insert") 070 int insert(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls); 071 072 073 074 /** 075 * 批量插入 entity 数据,只会根据第一条数据来构建插入的字段内容 076 * 077 * @param entities 插入的数据列表 078 * @return 返回影响的行数 079 * @see com.mybatisflex.core.provider.EntitySqlProvider#insertBatch(Map, ProviderContext) 080 * @see com.mybatisflex.core.FlexConsts#METHOD_INSERT_BATCH 081 */ 082 @InsertProvider(type = EntitySqlProvider.class, method = FlexConsts.METHOD_INSERT_BATCH) 083 int insertBatch(@Param(FlexConsts.ENTITIES) List<T> entities); 084 085 /** 086 * 批量插入 entity 数据,按 size 切分 087 * 088 * @param entities 插入的数据列表 089 * @param size 切分大小 090 * @return 影响行数 091 */ 092 default int insertBatch(List<T> entities, int size) { 093 if (size <= 0) { 094 size = 1000;//默认1000 095 } 096 int sum = 0; 097 int entitiesSize = entities.size(); 098 int maxIndex = entitiesSize / size + (entitiesSize % size == 0 ? 0 : 1); 099 for (int i = 0; i < maxIndex; i++) { 100 List<T> list = entities.subList(i * size, Math.min(i * size + size, entitiesSize)); 101 sum += insertBatch(list); 102 } 103 return sum; 104 } 105 106 /** 107 * 新增 或者 更新,若主键有值,则更新,若没有主键值,则插入 108 * 109 * @param entity 实体类 110 * @return 返回影响的行数 111 */ 112 default int insertOrUpdate(T entity) { 113 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass()); 114 Object[] pkArgs = tableInfo.buildPkSqlArgs(entity); 115 if (pkArgs.length == 0 || pkArgs[0] == null) { 116 return insert(entity); 117 } else { 118 return update(entity); 119 } 120 } 121 122 /** 123 * 根据 id 删除数据 124 * 如果是多个主键的情况下,需要传入数组 new Object[]{100,101} 125 * 126 * @param id 主键数据 127 * @return 返回影响的行数 128 * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteById(Map, ProviderContext) 129 */ 130 @DeleteProvider(type = EntitySqlProvider.class, method = "deleteById") 131 int deleteById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id); 132 133 134 /** 135 * 根据多个 id 批量删除数据 136 * 137 * @param ids ids 列表 138 * @return 返回影响的行数 139 * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext) 140 */ 141 @DeleteProvider(type = EntitySqlProvider.class, method = "deleteBatchByIds") 142 int deleteBatchByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids); 143 144 /** 145 * 根据多个 id 批量删除数据 146 * 147 * @param ids ids 列表 148 * @param size 切分大小 149 * @return 返回影响的行数 150 * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteBatchByIds(Map, ProviderContext) 151 */ 152 default int deleteBatchByIds(@Param(FlexConsts.PRIMARY_VALUE) List<? extends Serializable> ids, int size) { 153 if (size <= 0) { 154 size = 1000;//默认1000 155 } 156 int sum = 0; 157 int entitiesSize = ids.size(); 158 int maxIndex = entitiesSize / size + (entitiesSize % size == 0 ? 0 : 1); 159 for (int i = 0; i < maxIndex; i++) { 160 List<? extends Serializable> list = ids.subList(i * size, Math.min(i * size + size, entitiesSize)); 161 sum += deleteBatchByIds(list); 162 } 163 return sum; 164 } 165 166 167 /** 168 * 根据 map 构建的条件来删除数据 169 * 170 * @param whereConditions 条件 171 * @return 返回影响的行数 172 */ 173 default int deleteByMap(Map<String, Object> whereConditions) { 174 if (ObjectUtil.areNull(whereConditions) || whereConditions.isEmpty()) { 175 throw FlexExceptions.wrap("deleteByMap is not allow empty map."); 176 } 177 return deleteByQuery(QueryWrapper.create().where(whereConditions)); 178 } 179 180 /** 181 * 根据条件来删除数据 182 * 183 * @param condition 条件 184 * @return 返回影响的行数 185 */ 186 default int deleteByCondition(QueryCondition condition) { 187 return deleteByQuery(QueryWrapper.create().where(condition)); 188 } 189 190 /** 191 * 根据 query 构建的条件来数据吗 192 * 193 * @param queryWrapper query 条件 194 * @return 返回影响的行数 195 * @see com.mybatisflex.core.provider.EntitySqlProvider#deleteByQuery(Map, ProviderContext) 196 */ 197 @DeleteProvider(type = EntitySqlProvider.class, method = "deleteByQuery") 198 int deleteByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper); 199 200 201 /** 202 * 根据主键来更新数据,若 entity 属性数据为 null,该属性不会新到数据库 203 * 204 * @param entity 数据内容,必须包含有主键 205 * @return 返回影响的行数 206 */ 207 default int update(T entity) { 208 return update(entity, true); 209 } 210 211 /** 212 * 根据主键来更新数据到数据库 213 * 214 * @param entity 数据内容 215 * @param ignoreNulls 是否忽略空内容字段 216 * @return 返回影响的行数 217 * @see com.mybatisflex.core.provider.EntitySqlProvider#update(Map, ProviderContext) 218 */ 219 @UpdateProvider(type = EntitySqlProvider.class, method = "update") 220 int update(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls); 221 222 223 /** 224 * 根据 map 构建的条件来更新数据 225 * 226 * @param entity 数据 227 * @param map where 条件内容 228 * @return 返回影响的行数 229 */ 230 default int updateByMap(T entity, Map<String, Object> map) { 231 return updateByQuery(entity, QueryWrapper.create().where(map)); 232 } 233 234 /** 235 * 根据 condition 来更新数据 236 * 237 * @param entity 数据 238 * @param condition 条件 239 * @return 返回影响的行数 240 */ 241 default int updateByCondition(T entity, QueryCondition condition) { 242 return updateByQuery(entity, QueryWrapper.create().where(condition)); 243 } 244 245 /** 246 * 根据 condition 来更新数据 247 * 248 * @param entity 数据 249 * @param ignoreNulls 是否忽略 null 数据,默认为 true 250 * @param condition 条件 251 * @return 返回影响的行数 252 */ 253 default int updateByCondition(T entity, boolean ignoreNulls, QueryCondition condition) { 254 return updateByQuery(entity, ignoreNulls, QueryWrapper.create().where(condition)); 255 } 256 257 258 /** 259 * 根据 query 构建的条件来更新数据 260 * 261 * @param entity 数据内容 262 * @param queryWrapper query 条件 263 * @return 返回影响的行数 264 */ 265 266 default int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper) { 267 return updateByQuery(entity, true, queryWrapper); 268 } 269 270 /** 271 * 根据 query 构建的条件来更新数据 272 * 273 * @param entity 数据内容 274 * @param ignoreNulls 是否忽略空值 275 * @param queryWrapper query 条件 276 * @see com.mybatisflex.core.provider.EntitySqlProvider#updateByQuery(Map, ProviderContext) 277 */ 278 @UpdateProvider(type = EntitySqlProvider.class, method = "updateByQuery") 279 int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper); 280 281 282 /** 283 * 根据主键来选择数据 284 * 285 * @param id 多个主键 286 * @return entity 287 * @see com.mybatisflex.core.provider.EntitySqlProvider#selectOneById(Map, ProviderContext) 288 */ 289 @SelectProvider(type = EntitySqlProvider.class, method = "selectOneById") 290 T selectOneById(@Param(FlexConsts.PRIMARY_VALUE) Serializable id); 291 292 293 /** 294 * 根据 map 构建的条件来查询数据 295 * 296 * @param whereConditions where 条件 297 * @return entity 数据 298 */ 299 default T selectOneByMap(Map<String, Object> whereConditions) { 300 return selectOneByQuery(QueryWrapper.create().where(whereConditions)); 301 } 302 303 304 /** 305 * 根据 condition 来查询数据 306 * 307 * @param condition 条件 308 * @return 1 条数据 309 */ 310 default T selectOneByCondition(QueryCondition condition) { 311 return selectOneByQuery(QueryWrapper.create().where(condition)); 312 } 313 314 315 /** 316 * 根据 queryWrapper 构建的条件来查询 1 条数据 317 * 318 * @param queryWrapper query 条件 319 * @return entity 数据 320 */ 321 default T selectOneByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper) { 322 List<T> entities = selectListByQuery(queryWrapper.limit(1)); 323 return (entities == null || entities.isEmpty()) ? null : entities.get(0); 324 } 325 326 /** 327 * 根据多个主键来查询多条数据 328 * 329 * @param ids 主键列表 330 * @return 数据列表 331 * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByIds(Map, ProviderContext) 332 */ 333 @SelectProvider(type = EntitySqlProvider.class, method = "selectListByIds") 334 List<T> selectListByIds(@Param(FlexConsts.PRIMARY_VALUE) Collection<? extends Serializable> ids); 335 336 337 /** 338 * 根据 map 来构建查询条件,查询多条数据 339 * 340 * @param whereConditions 条件列表 341 * @return 数据列表 342 */ 343 default List<T> selectListByMap(Map<String, Object> whereConditions) { 344 return selectListByQuery(QueryWrapper.create().where(whereConditions)); 345 } 346 347 348 /** 349 * 根据 map 来构建查询条件,查询多条数据 350 * 351 * @param whereConditions 条件列表 352 * @return 数据列表 353 */ 354 default List<T> selectListByMap(Map<String, Object> whereConditions, int count) { 355 return selectListByQuery(QueryWrapper.create().where(whereConditions).limit(count)); 356 } 357 358 359 /** 360 * 根据 condition 来查询数据 361 * 362 * @param condition condition 条件 363 * @return 数据列表 364 */ 365 default List<T> selectListByCondition(QueryCondition condition) { 366 return selectListByQuery(QueryWrapper.create().where(condition)); 367 } 368 369 370 /** 371 * 根据 condition 来查询数据 372 * 373 * @param condition condition 条件 374 * @param count 数据量 375 * @return 数据列表 376 */ 377 default List<T> selectListByCondition(QueryCondition condition, int count) { 378 return selectListByQuery(QueryWrapper.create().where(condition).limit(count)); 379 } 380 381 382 /** 383 * 根据 query 来构建条件查询数据列表 384 * 385 * @param queryWrapper 查询条件 386 * @return 数据列表 387 * @see com.mybatisflex.core.provider.EntitySqlProvider#selectListByQuery(Map, ProviderContext) 388 */ 389 @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery") 390 List<T> selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper); 391 392 393 /** 394 * 查询全部数据 395 * 396 * @return 数据列表 397 */ 398 default List<T> selectAll() { 399 return selectListByQuery(new QueryWrapper()); 400 } 401 402 403 /** 404 * 根据条件查询数据总量 405 * 406 * @param condition 条件 407 * @return 数据量 408 */ 409 default long selectCountByCondition(QueryCondition condition) { 410 return selectCountByQuery(QueryWrapper.create().where(condition)); 411 } 412 413 414 /** 415 * 根据 queryWrapper 来查询数据量 416 * 417 * @param queryWrapper 查询包装器 418 * @return 数据量 419 * @see EntitySqlProvider#selectCountByQuery(Map, ProviderContext) 420 */ 421 @SelectProvider(type = EntitySqlProvider.class, method = "selectCountByQuery") 422 long selectCountByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper); 423 424 425 /** 426 * 分页查询 427 * 428 * @param pageNumber 当前页码 429 * @param pageSize 每页的数据量 430 * @param queryWrapper 查询条件 431 * @return 返回 Page 数据 432 */ 433 default Page<T> paginate(int pageNumber, int pageSize, QueryWrapper queryWrapper) { 434 Page<T> page = new Page<>(pageNumber, pageSize); 435 return paginate(page, queryWrapper); 436 } 437 438 439 /** 440 * 根据条件分页查询 441 * 442 * @param pageNumber 当前页面 443 * @param pageSize 每页的数据量 444 * @param condition 查询条件 445 * @return 返回 Page 数据 446 */ 447 default Page<T> paginate(int pageNumber, int pageSize, QueryCondition condition) { 448 Page<T> page = new Page<>(pageNumber, pageSize); 449 return paginate(page, new QueryWrapper().where(condition)); 450 } 451 452 /** 453 * 分页查询 454 * 455 * @param pageNumber 当前页码 456 * @param pageSize 每页的数据量 457 * @param totalRow 数据总量 458 * @param queryWrapper 查询条件 459 * @return 返回 Page 数据 460 */ 461 default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryWrapper queryWrapper) { 462 Page<T> page = new Page<>(pageNumber, pageSize, totalRow); 463 return paginate(page, queryWrapper); 464 } 465 466 467 /** 468 * 根据条件分页查询 469 * 470 * @param pageNumber 当前页面 471 * @param pageSize 每页的数据量 472 * @param totalRow 数据总量 473 * @param condition 查询条件 474 * @return 返回 Page 数据 475 */ 476 default Page<T> paginate(int pageNumber, int pageSize, int totalRow, QueryCondition condition) { 477 Page<T> page = new Page<>(pageNumber, pageSize, totalRow); 478 return paginate(page, new QueryWrapper().where(condition)); 479 } 480 481 482 /** 483 * 分页查询 484 * 485 * @param page page,其包含了页码、每页的数据量,可能包含数据总量 486 * @param queryWrapper 查询条件 487 * @return page 数据 488 */ 489 default Page<T> paginate(@Param("page") Page<T> page, @Param("query") QueryWrapper queryWrapper) { 490 491 List<QueryColumn> groupByColumns = null; 492 493 // 只有 totalRow 小于 0 的时候才会去查询总量 494 // 这样方便用户做总数缓存,而非每次都要去查询总量 495 // 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的 496 if (page.getTotalRow() < 0) { 497 groupByColumns = CPI.getGroupByColumns(queryWrapper); 498 //清除group by 去查询数据 499 CPI.setGroupByColumns(queryWrapper, null); 500 long count = selectCountByQuery(queryWrapper); 501 page.setTotalRow(count); 502 } 503 504 if (page.getTotalRow() == 0 || page.getPageNumber() > page.getTotalPage()) { 505 return page; 506 } 507 508 //恢复数量查询清除的 groupBy 509 if (groupByColumns != null) { 510 CPI.setGroupByColumns(queryWrapper, groupByColumns); 511 } 512 513 int offset = page.getPageSize() * (page.getPageNumber() - 1); 514 queryWrapper.limit(offset, page.getPageSize()); 515 List<T> rows = selectListByQuery(queryWrapper); 516 page.setRecords(rows); 517 return page; 518 } 519}