1.1 ServiceImpl实现类:
/* * Copyright (c) 2011-2020, baomidou (jobob@qq.com). * <p> * 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 * <p> * https://www.apache.org/licenses/LICENSE-2.0 * <p> * 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.impl; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.*; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import org.apache.ibatis.binding.MapperMethod; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.reflection.ExceptionUtil; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.MyBatisExceptionTranslator; import org.mybatis.spring.SqlSessionHolder; import org.mybatis.spring.SqlSessionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronizationManager; import java.io.Serializable; import java.util.Collection; import java.util.Map; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; /** * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) * * @author hubin * @since 2018-06-23 */ @SuppressWarnings("unchecked") public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> { protected Log log = LogFactory.getLog(getClass()); @Autowired protected M baseMapper; @Override public M getBaseMapper() { return baseMapper; } protected Class<?> entityClass = currentModelClass(); /** * 判断数据库操作是否成功 * * @param result 数据库操作返回影响条数 * @return boolean * @deprecated 3.3.1 */ @Deprecated protected boolean retBool(Integer result) { return SqlHelper.retBool(result); } protected Class<T> currentModelClass() { return (Class<T>) ReflectionKit.getSuperClassGenericType(getClass(), 1); } /** * 批量操作 SqlSession * * @deprecated 3.3.0 */ @Deprecated protected SqlSession sqlSessionBatch() { return SqlHelper.sqlSessionBatch(entityClass); } /** * 释放sqlSession * * @param sqlSession session * @deprecated 3.3.0 */ @Deprecated protected void closeSqlSession(SqlSession sqlSession) { SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(entityClass)); } /** * 获取 SqlStatement * * @param sqlMethod ignore * @return ignore */ protected String sqlStatement(SqlMethod sqlMethod) { return SqlHelper.table(entityClass).getSqlStatement(sqlMethod.getMethod()); } /** * 批量插入 * * @param entityList ignore * @param batchSize ignore * @return ignore */ @Transactional(rollbackFor = Exception.class) @Override public boolean saveBatch(Collection<T> entityList, int batchSize) { String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE); return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); } /** * TableId 注解存在更新记录,否插入一条记录 * * @param entity 实体对象 * @return boolean */ @Transactional(rollbackFor = Exception.class) @Override public boolean saveOrUpdate(T entity) { if (null != entity) { Class<?> cls = entity.getClass(); TableInfo tableInfo = TableInfoHelper.getTableInfo(cls); Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); String keyProperty = tableInfo.getKeyProperty(); Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty()); return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity); } return false; } @Transactional(rollbackFor = Exception.class) @Override public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) { TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); String keyProperty = tableInfo.getKeyProperty(); Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); return executeBatch(entityList, batchSize, (sqlSession, entity) -> { Object idVal = ReflectionKit.getMethodValue(entityClass, entity, keyProperty); if (StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal))) { sqlSession.insert(tableInfo.getSqlStatement(SqlMethod.INSERT_ONE.getMethod()), entity); } else { MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>(); param.put(Constants.ENTITY, entity); sqlSession.update(tableInfo.getSqlStatement(SqlMethod.UPDATE_BY_ID.getMethod()), param); } }); } @Transactional(rollbackFor = Exception.class) @Override public boolean updateBatchById(Collection<T> entityList, int batchSize) { String sqlStatement = sqlStatement(SqlMethod.UPDATE_BY_ID); return executeBatch(entityList, batchSize, (sqlSession, entity) -> { MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>(); param.put(Constants.ENTITY, entity); sqlSession.update(sqlStatement, param); }); } @Override public T getOne(Wrapper<T> queryWrapper, boolean throwEx) { if (throwEx) { return baseMapper.selectOne(queryWrapper); } return SqlHelper.getObject(log, baseMapper.selectList(queryWrapper)); } @Override public Map<String, Object> getMap(Wrapper<T> queryWrapper) { return SqlHelper.getObject(log, baseMapper.selectMaps(queryWrapper)); } @Override public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) { return SqlHelper.getObject(log, listObjs(queryWrapper, mapper)); } /** * 执行批量操作 * * @param consumer consumer * @since 3.3.0 * @deprecated 3.3.1 后面我打算移除掉 {@link #executeBatch(Collection, int, BiConsumer)} }. */ @Deprecated protected boolean executeBatch(Consumer<SqlSession> consumer) { SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(entityClass); SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory); boolean transaction = TransactionSynchronizationManager.isSynchronizationActive(); if (sqlSessionHolder != null) { SqlSession sqlSession = sqlSessionHolder.getSqlSession(); //原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session //按道理来说,这里的值应该一直为false。 sqlSession.commit(!transaction); } SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); if (!transaction) { log.warn("SqlSession [" + sqlSession + "] was not registered for synchronization because DataSource is not transactional"); } try { consumer.accept(sqlSession); //非事物情况下,强制commit。 sqlSession.commit(!transaction); return true; } catch (Throwable t) { sqlSession.rollback(); Throwable unwrapped = ExceptionUtil.unwrapThrowable(t); if (unwrapped instanceof RuntimeException) { MyBatisExceptionTranslator myBatisExceptionTranslator = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true); throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped)); } throw ExceptionUtils.mpe(unwrapped); } finally { sqlSession.close(); } } /** * 执行批量操作 * * @param list 数据集合 * @param batchSize 批量大小 * @param consumer 执行方法 * @param <E> 泛型 * @return 操作结果 * @since 3.3.1 */ protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) { Assert.isFalse(batchSize < 1, "batchSize must not be less than one"); return !CollectionUtils.isEmpty(list) && executeBatch(sqlSession -> { int size = list.size(); int i = 1; for (E element : list) { consumer.accept(sqlSession, element); if ((i % batchSize == 0) || i == size) { sqlSession.flushStatements(); } i++; } }); } /** * 执行批量操作(默认批次提交数量{@link IService#DEFAULT_BATCH_SIZE}) * * @param list 数据集合 * @param consumer 执行方法 * @param <E> 泛型 * @return 操作结果 * @since 3.3.1 */ protected <E> boolean executeBatch(Collection<E> list, BiConsumer<SqlSession, E> consumer) { return executeBatch(list, DEFAULT_BATCH_SIZE, consumer); } }
2.0 实现IService接口
我们有了之前学习BaseMapd的经验之后我们来看些mapper的自带的service的方法有哪些妙用;
2.1 创建Service 层Impl 层
**UserService:**继承了mapper-plus的IService
package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.pojo.User; public interface UserService extends IService<User> { }
**UserServiceImpl:**继承了mapper-plus的ServiceImpl;我们传入的2个值一个是mapper(mapper接口)一个是user(实体类)
package com.example.service.Impl; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.mapper.UserMapper; import com.example.pojo.User; import com.example.service.UserService; import org.springframework.stereotype.Service; @Service public class UserSercieImpl extends ServiceImpl<UserMapper,User> implements UserService { }
2.2 写测试类
新建 MyBatisPlusService 测试类;
package com.example; import com.example.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 MYBatisPlusService { //引用servies的方法 @Autowired private UserService userService; }
2.3 查询全部条数;
/** * 查询总条数 */ @Test public void SelectCount(){ int count = userService.count(); System.out.println("count"+count); }
执行结果:
==> Preparing: SELECT COUNT( 1 ) FROM user ==> Parameters: <== Columns: COUNT( 1 ) <== Row: 5 <== Total: 1
2.4 根据id删除;
/** * 根据id删除 */ @Test public void removeById(){ boolean count = userService.removeById(3L); System.out.println("count"+count); if (count){ System.out.println("删除成功"); }else { System.out.println("删除失败"); }
运行结果是
==> Preparing: DELETE FROM user WHERE id=? ==> Parameters: 3(Long) <== Updates: 1
2.5 批量添加;
/** * 批量添加 */ @Test public void removeById1(){ List<User> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { User user = new User(); user.setName("闫文超"+i); user.setAge(10+i); user.setEmail("757631644"+i+i+1); list.add(user); } boolean count = userService.saveBatch(list); System.out.println("count"+count); if (count){ System.out.println("批量添加成功"); }else { System.out.println("批量添加失败"); } }
运行结果为:
==> Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) ==> Parameters: 1577321026130407426(Long), 闫文超0(String), 10(Integer), 757631644001(String) ==> Parameters: 1577321026298179585(Long), 闫文超1(String), 11(Integer), 757631644111(String) ==> Parameters: 1577321026298179586(Long), 闫文超2(String), 12(Integer), 757631644221(String) ==> Parameters: 1577321026298179587(Long), 闫文超3(String), 13(Integer), 757631644331(String) ==> Parameters: 1577321026298179588(Long), 闫文超4(String), 14(Integer), 757631644441(String) ==> Parameters: 1577321026298179589(Long), 闫文超5(String), 15(Integer), 757631644551(String) ==> Parameters: 1577321026298179590(Long), 闫文超6(String), 16(Integer), 757631644661(String) ==> Parameters: 1577321026298179591(Long), 闫文超7(String), 17(Integer), 757631644771(String) ==> Parameters: 1577321026298179592(Long), 闫文超8(String), 18(Integer), 757631644881(String) ==> Parameters: 1577321026298179593(Long), 闫文超9(String), 19(Integer), 757631644991(String) counttrue 批量添加成功
此次service的演示到此为止;大家也可以根据接口实现去看看都有哪些实现;大家也可以去尝试下其他的玩法;由于内容太过简单;我这边就不多做介绍了;
大家有任何问题都可以留言;