public class MybatisBatchUtils {
/**
* 每次處理1000條
*/
private static final int BATCH_SIZE = 1000;
@Resource
private SqlSessionFactory sqlSessionFactory;
/**
* 批量處理修改或者插入
*
* @param data 需要被處理的數(shù)據(jù)
* @param mapperClass Mybatis的Mapper類(lèi)
* @param function 自定義處理邏輯
* @return int 影響的總行數(shù)
*/
public <T,U,R> int 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++;
}
// 非事務(wù)環(huán)境下強(qiáng)制commit,事務(wù)情況下該commit相當(dāng)于無(wú)效
batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
} catch (Exception e) {
batchSqlSession.rollback();
throw new CustomException(e);
} finally {
batchSqlSession.close();
}
return i - 1;
}
}
使用方式:
BiFunction<TestRecord, TestRecordMapper, Integer> function = (testRecord, testRecordMapper) -> {
int i = testRecordMapper.insertSelective(testRecord);
return i;
};
int i = mybatisBatchUtils.batchUpdateOrInsert(res, TestRecordMapper.class, function);
注意:
數(shù)據(jù)庫(kù)連接url配置為 url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&rewriteBatchedStatements=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&autoReconnect=true&serverTimezone=Asia/Shanghai
秩命,其中上岗,rewriteBatchedStatements參數(shù)
設(shè)置此參數(shù)為true, 會(huì)讓數(shù)據(jù)庫(kù)driver重寫(xiě)批量更新語(yǔ)句(批量插入和批量更新).
MySQL會(huì)從連接中獲取rewriteBatchedStatements參數(shù), 可通過(guò)在jdbc url中配置rewriteBatchedStatements=true讓它生效, 否則批量更新會(huì)退化成one-by-one執(zhí)行.