一、前言
用过mybatis-plus的同学应该对它的批量更新并不陌生,但mybatis-plus只提供了根据主键ID进行批量更新的updateBatchById
的方法,虽然非常好用,但是往往我们会遇到需要根据某个或者多个非ID字段进行批量更新,那这时候该怎么实现呢?
二、可行的方案
方案一
一种方案是直接拿到SqlSessionTemplate
,然后获取批量执行的sqlSession对象,类是如下代码:
@Autowired private SqlSessionTemplate sqlSessionTemplate; // 新获取一个模式为BATCH,自动提交为false的session SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH,false); static final BATCH_SIZE = 1000; XxxMapper xxMapper = session.getMapper(XxxMapper.class); int size = updateList.size(); try { for(int i=0; i < size; i++) { xxMapper.updateByXxx(updateList.get(i)); if(i % BATCH_SIZE == 0 || i == size-1){ //手动每1000个一提交,提交后无法回滚 session.commit(); //清理缓存,防止溢出 session.clearCache(); } } }catch (Exception e) { session.rollback(); } finally { session.close(); }
这其实就是使用了mybatis自身的方法,毕竟mybatis-plus只是对mybatis的补充,mybatis的所有功能还是照常可以使用的。这是一种方案,具体的就不展开了。
方案二
第二种方案就是我们仿照mybatis-plus的updateBatchById
的方法仿写一个根据指定字段批量更新的方法,因此我们先看下updateBatchById
的源码,具体如下:
public boolean updateBatchById(Collection<T> entityList, int batchSize) { String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE_BY_ID); return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> { ParamMap<T> param = new ParamMap(); param.put(Constants.ENTITY, entity); sqlSession.update(sqlStatement, param); }); }
注:Constants.ENTITY的值为“et”,Constants常量类在com.baomidou.mybatisplus.core.toolkit包下
接下来我们模仿实现下mybatis-plus根据某个指定字段批量更新的代码。
1、参考上面的代码,我们仿写一个根据指定的字段来批量更新数据库的代码,比如我这里只针对UserEntity
,在UserServiceImpl
下(该实现类是继承了mybatis-plus的ServiceImpl的)新增如下代码:
public boolean updateBatchByQueryWrapper(Collection<UserEntity> entityList, Function<UserEntity, QueryWrapper> queryWrapperFunction) { String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE); return this.executeBatch(entityList, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> { ParamMap param = new ParamMap(); param.put(Constants.ENTITY, entity); param.put(Constants.WRAPPER, queryWrapperFunction.apply(entity)); sqlSession.update(sqlStatement, param); }); }
注意:
1)这里使用了Function函数式接口,如果不知道请查看Java函数式编程入门学习举例与优点详解2)batchSize这里默认使用DEFAULT_BATCH_SIZE,也是mybatis-plus中的默认值1000,当然你也可以保留该入参
3)主要核心的修改地方是以下两部分:
// SqlMethod.UPDATE_BY_ID改为SqlMethod.UPDATE String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE); //和新增如下的wapper,即更新条件 param.put(Constants.WRAPPER, queryWrapperFunction.apply(entity));
2、实现了根据指定字段批量更新代码应该如何去使用?
我们只需调用类似如下如下代码,比如我们这里根据username
更新:
userService.updateBatchByQueryWrapper(userList, user->new QueryWrapper<>().eq("username",user.getUsername()));
如果你有多个更新条件,就构建对应的QueryWrapper
就可以了,到此该问题就解决了。
总结
好了,以上就是mybatis-plus根据某个指定字段实现批量更新数据库的全部内容。如果你有更好的方案,请留言。