Spring源码分析——JdbcTemplate执行批量insert操作
最近用到一个方法:
@Override public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException { if (logger.isDebugEnabled()) { logger.debug("Executing SQL batch update [" + sql + "]"); } return execute(sql, new PreparedStatementCallback<int[]>() { @Override public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException { try { int batchSize = pss.getBatchSize(); InterruptibleBatchPreparedStatementSetter ipss = (pss instanceof InterruptibleBatchPreparedStatementSetter ? (InterruptibleBatchPreparedStatementSetter) pss : null); if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) { for (int i = 0; i < batchSize; i++) { pss.setValues(ps, i); if (ipss != null && ipss.isBatchExhausted(i)) { break; } ps.addBatch(); } return ps.executeBatch(); } else { List<Integer> rowsAffected = new ArrayList<Integer>(); for (int i = 0; i < batchSize; i++) { pss.setValues(ps, i); if (ipss != null && ipss.isBatchExhausted(i)) { break; } rowsAffected.add(ps.executeUpdate()); } int[] rowsAffectedArray = new int[rowsAffected.size()]; for (int i = 0; i < rowsAffectedArray.length; i++) { rowsAffectedArray[i] = rowsAffected.get(i); } return rowsAffectedArray; } } finally { if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); }
在Mysql中,是支持批量插入的,语法为inset into 那个表 values+ 一堆值;在JdbcTemplate中,提供了方便批量插入的方法。先拼接出基本的sql,然后利用PreparementStatement的addBatch方法,将需要执行sql语句批量插入。
这段代码在小数据的测试时候,是没有问题的。但是当我拿2w条数据测试的时候,速度就慢的让人难以忍受。so,让我们重新审视这段代码。逻辑没问题,这时候会发现,怎么代码里面没有事务控制。
是的,一般我们的事务控制都交给spring统一管理了,比如,特别常见的事务配置,使用DataSourceTransactionManager这个类来切入service方法,进行事务管理,如果这么玩儿的话,在执行你真正的service方法之前,会先执行下面的方法:
/** * This implementation sets the isolation level but ignores the timeout. */ @Override protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); // Switch to manual commit if necessary. This is very expensive in some JDBC drivers, // so we don't want to do it unnecessarily (for example if we've explicitly // configured the connection pool to set it already). if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // Bind the session holder to the thread. if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, this.dataSource); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
先关闭手动提交事务,之后所有操作执行完成,再统一提交事务。很不幸,如果你使用了jdbcTemplate批量更新,但是又没有配置任何事务,就会出现这种情况:你批量插入两天条数据,代码写法上没有任何问题,你不断selet count(0) from你的操作表,你会发现,此时,数据是一条一条提交的,也就是说,你此时正在使用的是mySql的默认自动提交事务,2w条数据测试都慢死你,if more。。。。
但是当你切入了事务,你就节省掉了事务那部分开销时间,只提交一次。
Spring源码分析——JdbcTemplate执行批量insert操作的更多相关文章
- Spring源码解析-JdbcTemplate
JdbcTemplate类图 从类继承关系上来看,JdbcTemplate继承了基类JdbcAccessor和接口类JdbcOperation,在基类JdbcAccessor的设计中,对DataSou ...
- spring源码分析之spring-core总结篇
1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- 【Spring源码分析】Bean加载流程概览
代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)
代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)
doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...
- 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作
前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...
- 【Spring源码分析】原型Bean实例化过程、byName与byType及FactoryBean获取Bean源码实现
原型Bean加载过程 之前的文章,分析了非懒加载的单例Bean整个加载过程,除了非懒加载的单例Bean之外,Spring中还有一种Bean就是原型(Prototype)的Bean,看一下定义方式: & ...
- 【Spring源码分析】配置文件读取流程
前言 Spring配置文件读取流程本来是和http://www.cnblogs.com/xrq730/p/6285358.html一文放在一起的,这两天在看Spring自定义标签的时候,感觉对Spri ...
随机推荐
- js实现抛物线运动 兼容IE低版本(转)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- git branch 进入编辑状态
命令行输入git branch,发现进入编辑状态,都要:wq,非常不方便,这样配置 git config --global core.pager ''
- 理解JavaScript闭包(closure)
闭包听了很多次了,可是到底有那些具体的用法还是不清楚,看了<JavaScript高级程序设计>,有点明白了. 1.闭包的定义: 闭包其实就是一个函数,而这个函数有点特别,它能够访问另一个函 ...
- 相机姿态估计(Pose Estimation)
(未完待续.....) 根据针孔相机模型,相机成像平面一点的像素坐标p和该点在世界坐标系下的3D坐标P有$p=KP$的关系,如果用齐次坐标表示则有: $$dp=KP$$ 其中d是空间点深度(为了将p的 ...
- Java实现 lower_bound() 和 upper_bound()
Java实现 lower_bound() 和 upper_bound() lower_bound() 函数 lower_bound() 在 [begin, end) 进行二分查找,返回 大于或等于 t ...
- VS2013 类向导 "异常来自 HRESULT:0x8CE0000B" 解决方法
转自 http://blog.csdn.net/skyloveyue/article/details/52105912 我用使用了第二种方法: 改变项目的位置 将项目从原来D盘的位置(D:\proje ...
- 使用Storyboard拖线容易出错的地方
使用Storyboard拖线容易出错的地方: 在Storyboard中,选中某个控件,按住ctrl键进行拖线,建立Outlet和Action后,不能手动再去修改自动生成的代码,然后再次进行连线,这样会 ...
- 调用WebService报错404问题 (转载)
我想在MVC4的项目添加一个webservice文件,访问没问题,但是最后调用方法就报404错误. 但是如果我全新ASP.NET 空Web应用程序 然后再添加一个webservice文件,就一切OK. ...
- sharepoint OOS巨大坑
首先,我们安装的操作系统是windows server 2016 datacenter最新版,然后安装了OOS2016年的那个版本,打好语言包,安装必备软件,所有的步骤都没问题,但是你配置OOS场的时 ...
- 定位权限授权 - iOS
关于介入地图相关功能后会遇到类似定位的子功能,由此引来了此定位权限授权相关. 首先,需要导入 CoreLocation 的框架并创建管理对象从而实现后续的相关操作; #import <CoreL ...