通用Service接口
说明:
- 通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删 除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
- 泛型 T 为任意实体对象
- 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承
Mybatis-Plus 提供的基类 - 官网地址:https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F%
A3
IService
/** Copyright (c) 2011-2022, baomidou (jobob@qq.com).** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.baomidou.mybatisplus.extension.service;import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.ChainQuery;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.ChainUpdate;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.transaction.annotation.Transactional;import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 顶级 Service** @author hubin* @since 2018-06-23*/
public interface IService<T> {/*** 默认批次提交数量*/int DEFAULT_BATCH_SIZE = 1000;/*** 插入一条记录(选择字段,策略插入)** @param entity 实体对象*/default boolean save(T entity) {return SqlHelper.retBool(getBaseMapper().insert(entity));}/*** 插入(批量)** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean saveBatch(Collection<T> entityList) {return saveBatch(entityList, DEFAULT_BATCH_SIZE);}/*** 插入(批量)** @param entityList 实体对象集合* @param batchSize 插入批次数量*/boolean saveBatch(Collection<T> entityList, int batchSize);/*** 批量修改插入** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean saveOrUpdateBatch(Collection<T> entityList) {return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);}/*** 批量修改插入** @param entityList 实体对象集合* @param batchSize 每次的数量*/boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);/*** 根据 ID 删除** @param id 主键ID*/default boolean removeById(Serializable id) {return SqlHelper.retBool(getBaseMapper().deleteById(id));}/*** 根据 ID 删除** @param id 主键(类型必须与实体类型字段保持一致)* @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)* @return 删除结果* @since 3.5.0*/default boolean removeById(Serializable id, boolean useFill) {throw new UnsupportedOperationException("不支持的方法!");}/*** 根据实体(ID)删除** @param entity 实体* @since 3.4.4*/default boolean removeById(T entity) {return SqlHelper.retBool(getBaseMapper().deleteById(entity));}/*** 根据 columnMap 条件,删除记录** @param columnMap 表字段 map 对象*/default boolean removeByMap(Map<String, Object> columnMap) {Assert.notEmpty(columnMap, "error: columnMap must not be empty");return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));}/*** 根据 entity 条件,删除记录** @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default boolean remove(Wrapper<T> queryWrapper) {return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));}/*** 删除(根据ID 批量删除)** @param list 主键ID或实体列表*/default boolean removeByIds(Collection<?> list) {if (CollectionUtils.isEmpty(list)) {return false;}return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));}/*** 批量删除** @param list 主键ID或实体列表* @param useFill 是否填充(为true的情况,会将入参转换实体进行delete删除)* @return 删除结果* @since 3.5.0*/@Transactional(rollbackFor = Exception.class)default boolean removeByIds(Collection<?> list, boolean useFill) {if (CollectionUtils.isEmpty(list)) {return false;}if (useFill) {return removeBatchByIds(list, true);}return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));}/*** 批量删除(jdbc批量提交)** @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)* @return 删除结果* @since 3.5.0*/@Transactional(rollbackFor = Exception.class)default boolean removeBatchByIds(Collection<?> list) {return removeBatchByIds(list, DEFAULT_BATCH_SIZE);}/*** 批量删除(jdbc批量提交)** @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)* @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)* @return 删除结果* @since 3.5.0*/@Transactional(rollbackFor = Exception.class)default boolean removeBatchByIds(Collection<?> list, boolean useFill) {return removeBatchByIds(list, DEFAULT_BATCH_SIZE, useFill);}/*** 批量删除(jdbc批量提交)** @param list 主键ID或实体列表* @param batchSize 批次大小* @return 删除结果* @since 3.5.0*/default boolean removeBatchByIds(Collection<?> list, int batchSize) {throw new UnsupportedOperationException("不支持的方法!");}/*** 批量删除(jdbc批量提交)** @param list 主键ID或实体列表* @param batchSize 批次大小* @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)* @return 删除结果* @since 3.5.0*/default boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {throw new UnsupportedOperationException("不支持的方法!");}/*** 根据 ID 选择修改** @param entity 实体对象*/default boolean updateById(T entity) {return SqlHelper.retBool(getBaseMapper().updateById(entity));}/*** 根据 UpdateWrapper 条件,更新记录 需要设置sqlset** @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}*/default boolean update(Wrapper<T> updateWrapper) {return update(null, updateWrapper);}/*** 根据 whereEntity 条件,更新记录** @param entity 实体对象* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}*/default boolean update(T entity, Wrapper<T> updateWrapper) {return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));}/*** 根据ID 批量更新** @param entityList 实体对象集合*/@Transactional(rollbackFor = Exception.class)default boolean updateBatchById(Collection<T> entityList) {return updateBatchById(entityList, DEFAULT_BATCH_SIZE);}/*** 根据ID 批量更新** @param entityList 实体对象集合* @param batchSize 更新批次数量*/boolean updateBatchById(Collection<T> entityList, int batchSize);/*** TableId 注解存在更新记录,否插入一条记录** @param entity 实体对象*/boolean saveOrUpdate(T entity);/*** 根据 ID 查询** @param id 主键ID*/default T getById(Serializable id) {return getBaseMapper().selectById(id);}/*** 查询(根据ID 批量查询)** @param idList 主键ID列表*/default List<T> listByIds(Collection<? extends Serializable> idList) {return getBaseMapper().selectBatchIds(idList);}/*** 查询(根据 columnMap 条件)** @param columnMap 表字段 map 对象*/default List<T> listByMap(Map<String, Object> columnMap) {return getBaseMapper().selectByMap(columnMap);}/*** 根据 Wrapper,查询一条记录 <br/>* <p>结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default T getOne(Wrapper<T> queryWrapper) {return getOne(queryWrapper, true);}/*** 根据 Wrapper,查询一条记录** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}* @param throwEx 有多个 result 是否抛出异常*/T getOne(Wrapper<T> queryWrapper, boolean throwEx);/*** 根据 Wrapper,查询一条记录** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/Map<String, Object> getMap(Wrapper<T> queryWrapper);/*** 根据 Wrapper,查询一条记录** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}* @param mapper 转换函数*/<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);/*** 查询总记录数** @see Wrappers#emptyWrapper()*/default long count() {return count(Wrappers.emptyWrapper());}/*** 根据 Wrapper 条件,查询总记录数** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default long count(Wrapper<T> queryWrapper) {return SqlHelper.retCount(getBaseMapper().selectCount(queryWrapper));}/*** 查询列表** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default List<T> list(Wrapper<T> queryWrapper) {return getBaseMapper().selectList(queryWrapper);}/*** 查询所有** @see Wrappers#emptyWrapper()*/default List<T> list() {return list(Wrappers.emptyWrapper());}/*** 翻页查询** @param page 翻页对象* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {return getBaseMapper().selectPage(page, queryWrapper);}/*** 无条件翻页查询** @param page 翻页对象* @see Wrappers#emptyWrapper()*/default <E extends IPage<T>> E page(E page) {return page(page, Wrappers.emptyWrapper());}/*** 查询列表** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {return getBaseMapper().selectMaps(queryWrapper);}/*** 查询所有列表** @see Wrappers#emptyWrapper()*/default List<Map<String, Object>> listMaps() {return listMaps(Wrappers.emptyWrapper());}/*** 查询全部记录*/default List<Object> listObjs() {return listObjs(Function.identity());}/*** 查询全部记录** @param mapper 转换函数*/default <V> List<V> listObjs(Function<? super Object, V> mapper) {return listObjs(Wrappers.emptyWrapper(), mapper);}/*** 根据 Wrapper 条件,查询全部记录** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default List<Object> listObjs(Wrapper<T> queryWrapper) {return listObjs(queryWrapper, Function.identity());}/*** 根据 Wrapper 条件,查询全部记录** @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}* @param mapper 转换函数*/default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {return getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());}/*** 翻页查询** @param page 翻页对象* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}*/default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {return getBaseMapper().selectMapsPage(page, queryWrapper);}/*** 无条件翻页查询** @param page 翻页对象* @see Wrappers#emptyWrapper()*/default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {return pageMaps(page, Wrappers.emptyWrapper());}/*** 获取对应 entity 的 BaseMapper** @return BaseMapper*/BaseMapper<T> getBaseMapper();/*** 获取 entity 的 class** @return {@link Class<T>}*/Class<T> getEntityClass();/*** 以下的方法使用介绍:** 一. 名称介绍* 1. 方法名带有 query 的为对数据的查询操作, 方法名带有 update 的为对数据的修改操作* 2. 方法名带有 lambda 的为内部方法入参 column 支持函数式的* 二. 支持介绍** 1. 方法名带有 query 的支持以 {@link ChainQuery} 内部的方法名结尾进行数据查询操作* 2. 方法名带有 update 的支持以 {@link ChainUpdate} 内部的方法名为结尾进行数据修改操作** 三. 使用示例,只用不带 lambda 的方法各展示一个例子,其他类推* 1. 根据条件获取一条数据: `query().eq("column", value).one()`* 2. 根据条件删除一条数据: `update().eq("column", value).remove()`**//*** 链式查询 普通** @return QueryWrapper 的包装类*/default QueryChainWrapper<T> query() {return ChainWrappers.queryChain(getBaseMapper());}/*** 链式查询 lambda 式* <p>注意:不支持 Kotlin </p>** @return LambdaQueryWrapper 的包装类*/default LambdaQueryChainWrapper<T> lambdaQuery() {return ChainWrappers.lambdaQueryChain(getBaseMapper());}/*** 链式查询 lambda 式* kotlin 使用** @return KtQueryWrapper 的包装类*/default KtQueryChainWrapper<T> ktQuery() {return ChainWrappers.ktQueryChain(getBaseMapper(), getEntityClass());}/*** 链式查询 lambda 式* kotlin 使用** @return KtQueryWrapper 的包装类*/default KtUpdateChainWrapper<T> ktUpdate() {return ChainWrappers.ktUpdateChain(getBaseMapper(), getEntityClass());}/*** 链式更改 普通** @return UpdateWrapper 的包装类*/default UpdateChainWrapper<T> update() {return ChainWrappers.updateChain(getBaseMapper());}/*** 链式更改 lambda 式* <p>注意:不支持 Kotlin </p>** @return LambdaUpdateWrapper 的包装类*/default LambdaUpdateChainWrapper<T> lambdaUpdate() {return ChainWrappers.lambdaUpdateChain(getBaseMapper());}/*** <p>* 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法* 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作)* </p>** @param entity 实体对象*/default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {return update(entity, updateWrapper) || saveOrUpdate(entity);}
}
MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl,封装了常见的业务层逻辑
详情查看源码IService和ServiceImpl
创建Service接口和实现类
UserService.interface
package com.xxxx.mybatisplus.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.xxxx.mybatisplus.pojo.User;public interface UserService extends IService<User> {
}
UserServiceImpl
package com.xxxx.mybatisplus.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.mybatisplus.mapper.UserMapper;
import com.xxxx.mybatisplus.pojo.User;
import com.xxxx.mybatisplus.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
测试通过Service
查询总记录数
package com.xxxx.mybatisplus;import com.xxxx.mybatisplus.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MyBatisPlusServiceTest {@Autowiredprivate UserService userService;/*** 查询总记录数* SELECT COUNT( * ) FROM user*/@Testpublic void testGetCount(){long count = userService.count();System.out.println("总记录数 = "+count);}}
批量添加功能
@Testpublic void testInsertMore(){List<User> list = new ArrayList<>();for (int i = 1;i<=10;i++){User user = new User();user.setName("ybc"+i);user.setAge(20+i);list.add(user);}boolean b = userService.saveBatch(list);System.out.println(b);}