## 教程簡介 Django是一個開放源代碼的Web應用框架,由Python寫成。採用了MTV的框架模式,即模型M,視圖V和模版T。它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容為主的網站的,即是CMS(內容管理系統)軟體。Django是高水準的Python編程語言驅動的一個開源模型.視 ...
正常我們使用mybatis-plus插入的時候,首先想到的是 saveBatch 方法,不過看了下列印出來的sql和底層代碼,才發現它並不是真正的批量插入。
IService 中的代碼為
default boolean saveBatch(Collection<T> entityList) { return this.saveBatch(entityList, 1000); }
實現層 ServiceImpl 中的代碼為
public boolean saveBatch(Collection<T> entityList, int batchSize) { String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE); return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> { sqlSession.insert(sqlStatement, entity); }); }
SqlMethod.INSERT_ONE 的中文枚舉為
INSERT_ONE("insert", "插入一條數據(選擇欄位插入)", "<script>\nINSERT INTO %s %s VALUES %s\n</script>"),
通過監控控制台發現,它只是迴圈每1000條去插入,效率非常低。
參考網友的文章,找到一個支持批量操作的方法,下麵直接貼上代碼
1、添加批量操作參數類 CustomSqlInjector
/** * 支持自定義SQL註入方法 */ public class CustomSqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { // 獲取父類SQL註入方法列表 List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 將批量插入方法添加進去 methodList.add(new InsertBatchSomeColumn()); return methodList; } }
2、在MybatisPlusConfig中配置
@Bean public CustomSqlInjector customSqlInjector() { return new CustomSqlInjector(); }
3、添加自定義 Mapper介面
/** * 自定義Mapper,添加批量插入介面 * @param <T> */ @Mapper public interface CustomMapper<T> extends BaseMapper<T> { /** * 批量插入 * @param entityList 實體列表 * @return 影響行數 */ Integer insertBatchSomeColumn(Collection<T> entityList); }
4、將原來的Mapper業務介面,換成繼承此介面
@Mapper public interface StudentDao extends CustomMapper<Student> { List<Student> query(Student student); }
5、再進行測試一下
@Transactional //事務註解要加上 @Override public void testBatchCreate() { List<Student> list = new ArrayList<>(); int startIndex = this.lambdaQuery().select(Student::getId).count(); for (int i = 1; i <= 1000000; i++) { Student student = new Student(); Long id = SnowFlake.nextId(); student.setId(id); student.setCode("studentCode-" + (startIndex + i)); student.setName("studentName-" + (startIndex + i)); list.add(student); } Long startTime = System.currentTimeMillis(); System.out.println("開始批量操作:" + startTime); int count = this.baseMapper.insertBatchSomeColumn(list); Long endTime = System.currentTimeMillis(); System.out.println("完成批量操作:" + endTime); System.out.println("用時:" + (endTime - startTime)); System.out.println("保存成功:" + count); //this.saveBatch(list); }
測試結果為,1000000條數據,用時大概在 35秒左右
註意事項:
1、mysql會提示超過 max_allowed_packet 設置的最大值,到 my.cnf文件(windows為my.ini)修改就行了,我這直接改成 200M
2、此處為示例,實際業務中迴圈不要放在事務裡面