package com.cool.store.utils;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.function.BiConsumer;

@Component
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
public class MybatisBatchUtils {

    /**
     * 每次处理500条
     */
    private static final int BATCH_SIZE = 500;

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 批量处理修改或者插入
     *
     * @param data        需要被处理的数据
     * @param mapperClass Mybatis的Mapper类
     * @param consumer    自定义处理逻辑
     * @return int 影响的总行数
     * @author renwd
     */
    public <T, U> int batchInsertOrUpdate(List<T> data, Class<U> mapperClass, BiConsumer<T, U> consumer) {
        int i = 1;
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = sqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                consumer.accept(element, mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    sqlSession.flushStatements();
                }
                i++;
            }
            sqlSession.commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            sqlSession.close();
        }
        return i - 1;
    }
}
