mybatis-plus的saveBatch

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语句的。

你可能感兴趣的:(#,mybatis,mybatis)