首页 > 其他分享 >Mybatis-plus批量操作

Mybatis-plus批量操作

时间:2023-04-22 21:24:59浏览次数:47  
标签:批量 param entity sqlSession plus Mybatis

前言

使用Mybatis-plus可以很方便的实现批量新增和批量修改,不仅比自己写foreach遍历方便很多,而且性能也更加优秀。但是Mybatis-plus官方提供的批量修改和批量新增都是根据id来修改的,有时候我们需求其他字段,所以就需要我们自己修改一下。

一、批量修改

在Mybatis-plus的IService接口中有updateBatchById方法,我们常用以下方法根据id批量修改数据。

@Transactional(rollbackFor = Exception.class)
default boolean updateBatchById(Collection<T> entityList) {
return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
}

@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
String sqlStatement = getSqlStatement(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);
});
}

但是当我们想根据其他字段批量修改数据时,该方法就无能为力了。所以我们就可以根据第二个updateBatchById方法在自己的service类里面写一个新的批量新增方法。

public boolean updateBatchByColumn(Collection<?> entityList, String idCard) {
String sqlStatement = getSqlStatement(SqlMethod.UPDATE);
return executeBatch(entityList, (sqlSession, entity) -> {
LambdaUpdateWrapper<SysUser> updateWrapper = Wrappers.<SysUser>lambdaUpdate()
.eq(SysUser::getIdCard, idCard);
Map<String, Object> param = CollectionUtils.newHashMapWithExpectedSize(2);
param.put(Constants.ENTITY, entity);
param.put(Constants.WRAPPER, updateWrapper);
sqlSession.update(sqlStatement, param);
});
}

注意sqlStatement是使用的SqlMethod.UPDATE,SysUser对象是举例,使用的是若依的用户数据。

二、批量新增或修改

在Mybatis-plus的ServiceImpl 类中有一个saveOrUpdateBatch 方法用于批量新增或修改,通过CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity))根据id查询数据是否已存在,不存在新增,存在则修改,源码如下:

@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 SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
return StringUtils.checkValNull(idVal)
|| CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
}, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
});
}

最终调用的是SqlHelper.saveOrUpdateBatch方法,该方法第六个参数是BiPredicate,这就是用于判断数据库中数据是否存在的关键,所以我们需要修改这个函数式接口,修改为根据其他条件查询数据库。该方法的第七个参数是BiConsumer,该函数式接口用于修改数据,如果不想根据id修改数据,可以参考第一部门进行修改。

三、不使用Mybatis-plus进行批量操作

  有时候项目里没有引用Mybatis-plus,但是也想进行批量操作,数据量大了后foreach循环会影响性能。所以可以参考Mybatis-plus的批量操作,编写在mybatis环境下的批量操作,代码如下:

@Component
public class MybatisBatchUtils {

private static final int BATCH_SIZE = 1000;

@Autowired
private SqlSessionFactory sqlSessionFactory;

public <T,U,R> boolean batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function) {
int i = 1;
SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
U mapper = batchSqlSession.getMapper(mapperClass);
int size = data.size();
for (T element : data) {
function.apply(element, mapper);
if ((i % BATCH_SIZE == 0) || i == size) {
batchSqlSession.flushStatements();
}
i++;
}
// 非事务环境下强制commit,事务情况下该commit相当于无效
batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
return true;
} catch (Exception e) {
batchSqlSession.rollback();
throw new RuntimeException(e);
} finally {
batchSqlSession.close();
}
}
}

 

标签:批量,param,entity,sqlSession,plus,Mybatis
From: https://www.cnblogs.com/chuangsi/p/17343991.html

相关文章

  • Mysql Mybatis 批量修改数据
    MysqlMybatis批量修改数据MapperIntegerupdateListPO(List<ProjectQuotationItemPO>upateList);方法一:<updateid="updateListPO"><foreachcollection="list"separator=";"item="item">UPDATEpro......
  • 干货分享:用ChatGPT调教批量出Midjourney咒语,出图效率Nice ,附资料。
    Prompts就是AI绘图的核心竞争力。您是不是觉得用Midjourney生成的图不够完美?又让ChatGPT去生成Prompt,然后效果还不理想?其实ChatGPT你给他投喂资料后,经过调教的ChatGPT,生成的Prompt效果会很不错。文末附《一整套MidJourney指令大全》+《ChatGPTprompt指令大全》资料先看测试......
  • mybatis-plus使用聚合函数报错---------net.sf.jsqlparser.parser.ParseException: En
    错误日志: Causedby:net.sf.jsqlparser.parser.ParseException:Encounteredunexpectedtoken:"with""WITH"atline62,column20.Wasexpectingoneof:"&""::"";""<<&q......
  • mybatis总结
    mybatis总结 https://blog.csdn.net/qq_47540091/article/details/123446973Mybatisin逗号分隔字符串 <updateid="softDel"parameterType="String">SELECT*FROMstudyWHEREidin<foreachitem="item"index="inde......
  • mybatisplus更新字段为null怎么处理?
    mybatisplus更新字段为null怎么处理?  /***主键*/@TableId(type=IdType.ASSIGN_ID)@ApiModelProperty(value="主键")privateStringid;/***企业号*/@ApiModelProperty(value="企业号")@TableFi......
  • mybatisplus中update用法 update多个字段 mybatis-plus指定实体类字段不查询 mybatis-
     @OverridepublicbooleanupdateRiskverificationFlag(StringacptracctName){BmsBillRiskverificationbbr=newBmsBillRiskverification();bbr.setWarnflag("1");bbr.setUpdateBy("job");intnum=bill......
  • JDBC批量插入大量数据(高性能)
    rewriteBatchedStatements使用jdbc批量插入功能,rewriteBatchedStatements参数必不可少。对插入而言,所谓的rewrite其实就是将一批插入拼接成insertintoxxxvalues(a),(b),(c)...这样一条语句的形式然后执行,这样一来跟拼接sql的效果是一样的。但是此参数默认false,即便使用......
  • SpringBoot+Mybatis这个bug估计连作为神仙的您也无法解决--》Invalid bound statement
    最近开发一个调查单的应用系统,加班加点为了解决几个bug,但是最近两天卡在一个bug上。作为一头牛,不能轻易放弃,向困难挑战是牛的精神。1、Invalidbound问题展示首先,我针对题型QuestionType功能,写了五个子功能:增加题型,删除题型,修改题型,查询单条题型,模糊查询多条记录;还写了问题、调查......
  • SpringBoot+Mybatis-Plus+EasyExcel
    首先建立一个springboot项目,导入依赖<!--MyBatisPlus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version......
  • MyBatis删除
    删除单个IntegerdeleteOne(@Param("id")Stringid);===><deleteid="deleteOne">deletefromtb_userwhereid=#{id};</delete>===>@TestpublicvoiddeleteOne(){DeleteMappermapper=getMapper();......