IService.saveBatch
public interface IService<T> {
default boolean saveBatch(Collection<T> entityList) {
//
return this.saveBatch(entityList, 1000);
}
...
}
走到了ServiceImpl.saveBatch,最终走到了SqlHelper里面
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
public boolean saveBatch(Collection<T> entityList, int batchSize) {
//"com.bai.Mapper.insert"
String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
//携带真正的插入操作。entity代表着list里的每一个对象
//此处标记为1,
sqlSession.insert(sqlStatement, entity);
});
}
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
return SqlHelper.executeBatch(this.entityClass, this.log, list, batchSize, consumer);
}
看下SqlHelper
public final class SqlHelper {
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);
return !CollectionUtils.isEmpty(list)
//执行下面的executeBatch方法
//此处的consumer标记为2
&& executeBatch(entityClass, log, (sqlSession) -> {
int size = list.size();
int i = 1;
//按1000个一组批量
for(Iterator var6 = list.iterator(); var6.hasNext(); ++i) {
E element = var6.next();
//执行标记为1的地方
consumer.accept(sqlSession, element);
if (i % batchSize == 0 || i == size) {
// ID预占位
sqlSession.flushStatements();
}
}
});
}
public static boolean executeBatch(Class<?> entityClass, Log log, Consumer<SqlSession> consumer) {
try {
SqlSessionFactory sqlSessionFactory = sqlSessionFactory(entityClass);
SqlSessionHolder sqlSessionHolder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sqlSessionFactory);
boolean transaction = TransactionSynchronizationManager.isSynchronizationActive();
SqlSession sqlSession;
if (sqlSessionHolder != null) {
sqlSession = sqlSessionHolder.getSqlSession();
sqlSession.commit(!transaction);
}
sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
if (!transaction) {
log.warn("SqlSession [" + sqlSession + "] Transaction not enabled");
}
boolean var7;
try {
//执行标记为2的地方
consumer.accept(sqlSession);
//所有的都执行完后进行提交
sqlSession.commit(!transaction);
var7 = true;
} catch (Throwable var15) {
sqlSession.rollback();
Throwable unwrapped = ExceptionUtil.unwrapThrowable(var15);
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();
}
return var7;
} catch (Throwable var17) {
throw var17;
}
}
可以看到在批量插入时,如果使用saveBatch是N条sql语句,一次提交。
如果是for循环save,那是N条sql语句,N次提交。效率不可同日而语。
当然最好的应该是insert into value(1),(2),(3),(4)…这种一条sql语句的。