Mybatis Plus批量更新数据不忽略null值,在不修改全局配置的情况下
此文章记录的内容是如何在**不影响全局null值忽略配置**
的情况下,如何使用**mybatisplus**
进行**批量更新**
。
如果要在全局生效的话直接搜索MybatisPlus的null值忽略配置。
MyService.java#updateBatchWithNull
@Service
public class MyService extends MPJBaseServiceImpl<TestMapper, TestEntity> {
public boolean updateBatchWithNull(Long groupId, List<TestEntity> contents, int batchSize) {
// updateWithNull是TestMapper的方法
String sqlStatement = this.currentMapperClass().getName() + ".updateWithNull";
return executeBatch(contents, batchSize, (sqlSession, entity) -> {
entity.setGroupId(id);
sqlSession.update(sqlStatement, entity);
});
}
// 调用示例
@Transactional(rollbackFor = Exception.class)
public boolean saveByUser(Long groupId, List<TestEntity> list, Long userId){
// TODO 群管理员权限校验
// TODO 分离需要新增和更新的列表
List<TestEntity> insertList = null;
List<TestEntity> updateList = null;
// TODO 其他业务逻辑
if(CollectionUtils.isNotEmpty(insertList)){
saveBatch(insertList, 50);
}
if(CollectionUtils.isNotEmpty(updateList)){
updateBatchWithNull(insertList, 50);
}
return true;
}
}
TestMapper.java
int updateWithNull(TestEntity content);
TestMapper.xml
<!-- 批量更新包含null值的字段 -->
<update id="updateWithNull">
UPDATE my_table_name
<set>
<if test="groupId != null">group_id = #{groupId},</if>
<if test="name != null and name != ''">name = #{name,jdbcType=VARCHAR},</if>
<!--数据库里会被设置为null-->
play_content = #{playContent,jdbcType=VARCHAR},
hint_content = #{hintContent,jdbcType=VARCHAR},
<if test="updateBy != null">update_by = #{updateBy,jdbcType=VARCHAR},</if>
update_time = NOW()
</set>
WHERE id = #{id} and group_id = #{groupId} and del_flag = '0'
</update>
源码解析
// com.baomidou.mybatisplus.extension.toolkit.SqlHelper#executeBatch
public static <E> boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, 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(sqlSessionFactory, log, sqlSession -> {
int size = list.size();
int idxLimit = Math.min(batchSize, size);
int i = 1;
for (E element : list) {
consumer.accept(sqlSession, element);
if (i == idxLimit) {
sqlSession.flushStatements();
idxLimit = Math.min(idxLimit + batchSize, size);
}
i++;
}
});
}
// com.baomidou.mybatisplus.extension.toolkit.SqlHelper#executeBatch
public static boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer<SqlSession> consumer) {
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 + "] Transaction not enabled");
}
try {
consumer.accept(sqlSession);
//非事务情况下,强制commit。
sqlSession.commit(!transaction);
return true;
} catch (Throwable t) {
sqlSession.rollback();
Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
if (unwrapped instanceof PersistenceException) {
MyBatisExceptionTranslator myBatisExceptionTranslator
= new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
Throwable throwable = myBatisExceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (throwable != null) {
throw throwable;
}
}
throw ExceptionUtils.mpe(unwrapped);
} finally {
sqlSession.close();
}
}
// org.apache.ibatis.executor.BatchExecutor#doFlushStatements
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
List<BatchResult> results = new ArrayList<>();
if (isRollback) {
return Collections.emptyList();
}
for (int i = 0, n = statementList.size(); i < n; i++) {
Statement stmt = statementList.get(i);
applyTransactionTimeout(stmt);
BatchResult batchResult = batchResultList.get(i);
try {
batchResult.setUpdateCounts(stmt.executeBatch());
MappedStatement ms = batchResult.getMappedStatement();
List<Object> parameterObjects = batchResult.getParameterObjects();
KeyGenerator keyGenerator = ms.getKeyGenerator();
if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { // issue #141
for (Object parameter : parameterObjects) {
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
// Close statement to close cursor #1109
closeStatement(stmt);
} catch (BatchUpdateException e) {
StringBuilder message = new StringBuilder();
message.append(batchResult.getMappedStatement().getId()).append(" (batch index #").append(i + 1).append(")")
.append(" failed.");
if (i > 0) {
message.append(" ").append(i)
.append(" prior sub executor(s) completed successfully, but will be rolled back.");
}
throw new BatchExecutorException(message.toString(), e, results, batchResult);
}
results.add(batchResult);
}
return results;
} finally {
for (Statement stmt : statementList) {
closeStatement(stmt);
}
currentSql = null;
statementList.clear();
batchResultList.clear();
}
}
参考内容
上一篇: 几秒钟就充满电!科学
下一篇: 暂无数据