赞
踩
Mysql数据库批量插入大量数据时经常会遇到插入速度过慢的场景;自己也知道批量插入比单条插入也会快很多,后面测试又发现代码也得也没有问题可是执行结果总是差强人意,我也在测试过程中遇到此问题,后面发现是由于URL中缺少了参数导致: rewriteBatchedStatements=true
此参数默认配置是false,需要手动在URL中配置成true进行开启;开启了配置之后,就可以正常使用批量插入了,下面直接上Mybaits和Jdbc批处理的代码
- try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
- // 获取Mapper,一定要重新获取,否则不会走批处理
- XxMapper mapper = sqlSession.getMapper(XxMapper.class);
- // 循环插入数据
- for (Info info: infos) {
- mapper.insert(info);
- }
- // 批量提交
- sqlSession.commit();
- }
Mybatis批处理一定要从会话中获取Mapper对象;创建会话的过程会创建执行器并将执行器封装到会话中;创建执行器过程可以参考下面代码
- public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
- executorType = executorType == null ? defaultExecutorType : executorType;
- executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
- Executor executor;
- // 根据执行类型创建执行器
- if (ExecutorType.BATCH == executorType) {
- executor = new BatchExecutor(this, transaction);
- } else if (ExecutorType.REUSE == executorType) {
- executor = new ReuseExecutor(this, transaction);
- } else {
- executor = new SimpleExecutor(this, transaction);
- }
- if (cacheEnabled) {
- executor = new CachingExecutor(executor);
- }
- executor = (Executor) interceptorChain.pluginAll(executor);
- return executor;
- }
会话创建完成后,从会话中获取到的Mapper对象,调用Mapper对象的方法,会由JDK最终代理到会话中的执行器进行执行,会话又会交由执行器执行;可以参考下面代码
- @Override
- public int update(String statement, Object parameter) {
- try {
- dirty = true;
- MappedStatement ms = configuration.getMappedStatement(statement);
- // 执行器执行更新
- return executor.update(ms, wrapCollection(parameter));
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- String sql = "INSERT INTO TABLE(ID, USER_ID, USER_NO) VALUES(?, ?, ?)";
- try (Connection connection = dataSource.getConnection();
- PreparedStatement stmt = connection.prepareStatement(sql)) {
- // 关闭事务的自动提交
- connection.setAutoCommit(false);
- for (Info info: infos) {
- stmt.setString(1, info.getId());
- stmt.setString(2, info.getUserId());
- stmt.setString(3, info.getUserNo());
- // 添加到批处理
- stmt.addBatch();
- }
- // 执行批处理
- stmt.executeBatch();
- // 事务提交
- connection.commit();
- } catch (Exception e) {
- e.printStackTrace();
- }
如果批量插入的数据量在一万条以内的话,使用Mybatis的批处理与Jdbc的批处理在性能上区别不是很大;超过一万条的话还是建议使用Jdbc的批处理,性能上会好一些。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。