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 ...
随机推荐
- NET平台微服务
.NET平台微服务项目汇集 最近博客园出现了一篇文章<微服务时代之2017年五军之战:Net PHP谁先死>,掀起了一波撕逼,作者只是从一个使用者的角度来指点江山,这个姿势是不对的.. ...
- D3——绘制SVG图形-直方图
1.创建SVG元素 var svg = d3.select("body").append("svg"); 2.为SVG元素设置属性 svg.attr() .at ...
- 编程三基:cpu:算法,总线(io):一切皆文件;内存:运行空间
编程三基:cpu:算法,总线:一切皆文件:内存:数据.运行空间 原文找不到了.
- 2014年百度之星资格赛第一题Energy Conversion
Problem Description 魔法师百小度也有遇到难题的时候-- 如今.百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这样的魔法文字须要耗费大量的能量和大量的脑力. 过了许久 ...
- Server Error in '/' Application. 报错
控制面板--管理工具--服务--asp.netstate service 设置为自动,并启动
- 3springboot:springboot配置文件(配置文件、YAML、属性文件值注入<@Value、@ConfigurationProperties、@PropertySource,@ImportResource、@Bean>)
1.配置文件: springboot默认使用一个全局配置文件 配置文件名是固定的 配置文件有两种(开头均是application,主要是文件的后缀): ->application.prope ...
- js 模拟百度关键字搜索与跳转
测试效果: css样式: ul{ display:none; } html代码: <input type="text" id="text" /> & ...
- html拼接时onclick事件传递json对象
Bootstrap Table 中拼装onclick传递json对象会造成[object,object]错误,反正各种传值不成功, 应该是因为json对象中的‘’‘’引号冲突吧,直接把json对象转成 ...
- Spring 4 mvc+shiro+thymeleaf+JPA(Hibernate)+MySql eclipse项目模板
本模板基本配制为:spring 4.3.8+thymeleaf 3.0.3 +hibernate 5.5.5 + mysql 5.7 IDE:eclipse 运行环境为:Tomcat 8.0.28 项 ...
- java Thread 类 run 和 start 方法区别
public class ThreadModle { public static void main(String[] args) throws InterruptedException { Thre ...