使用JDBC批量保存数据(JdbcDaoSupport,JdbcTemplete)
最近做的一个项目中用到了Hibernate的,然后数据库批量插入数据的时候就使用到了hibernate的批处理,但是效率比较低,看网上说还有一些限制,要禁止二级缓存,还要多一个batch_size的配置什么的,不知道是用的不对还是怎么滴,插入一万条数据最快的时候也需要三十多秒时间,慢的五十多秒,比较纠结,然后改用了jdbc的批处理,这里有三张表,Device,Alarm和SyslogAlarm,不过device表可以忽略,用处不大,就是和Alarm有个一对多的关系,Alarm和SyslogAlarm的主键都是手动控制的,不自增,Alarm和SyslogAlarm是一对一的关系,现在控制Alarm和SyslogAlarm的主键值相同,即有关联关系的Alarm和SyslogAlarm的主键值相同,知道其中一个的主键就可以查出另外一张表,SyslogAlarm中有Alarm的外键,因此在这里也不能够让主键自增。
首先需要一个工具类,该工具类的作用是获取同一个Connection链接
//获取同一个connection,参照了hibernate的getCurrentSession的实现
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
public class ConnectionUtil{
public static final ThreadLocal<Connection> connections = new ThreadLocal<Connection>();
public static Connection getConnection(DataSource dataSource) throws SQLException{
Connection c = connections.get();
if(null==c){
c=dataSource.getConnection();
connections.set(c); }
return c;
}
}
spring的配置文件就不搞了下面是dao层的具体实现,servce层省略
@Repository
@Scope("prototype")
public class SyslogAlarmDao2 extends JdbcDaoSupport implements InitializingBean{
@resource
public void setDatasource(DataSource dataSource){
this.setDataSource(dataSource);
}
private long count = 0L;
String sql1 = "";
String sql2 = "";
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
Connection c = null;
/** 这里有篇文章可以帮助理解下面这个注解 http://blog.csdn.net/yaerfeng/article/details/8447530 */ @PostConstruct //
public void set() throws SQLException{
sql1 = "sql";//省略,带问号的sql字符串,注意字符串内容不能有;,比如"insert into alarm values(?,?,?,?,?,?);"就是错误的,我因为这个问题纠结了不少时间,"insert into alarm values(?,?,?,?,?,?)"
sql2 ="sql"; //同上
c = ConnectionUtil.getConnection(this.getDataSource());
ps1 = c.prepareStatement(sql1);
ps2 = c.prepareStatement(sql2); /** 由于主键是手动控制的,所以需要查一下数据库中已经存在的id的最大值,然后从最大值+1处开始添加数据 alarm和syslogalarm的主键值相同,所以查一个就可以 */
PreparedStatement ps3 = c.prepareStatement("select max(id) from alarm2");
ResultSet rs = ps3.executeQuery();
while(rs.next()){
count = rs.getLong();
}
}
public void executeBatch(SyslogAlarm sAlarm) throws SQLException{
//这个可以提取到service层 if(sAlarm==null||sAlarm.getAlarm ==null){
System.out.println("input error");
return;
} count++;
ps1.setLong(,count);
//从sAlarm中取值填充到ps1的sql字符串中 //..............
ps2.setLong(,count);
//从sAlarm中取值填充到ps2的sql字符串中 //..........
ps1.addBatch();
ps2.addBatch();
System.out.println("调用了 "+count+" 次");
==){ //为10的时候插入一万条需要4.061秒,为100插入一万数据需要1.403秒,为1000的时候插入一万条数据需要大概需要0.747秒时间
ps1.executeBatch();
ps2.executeBatch();
ps1.clearBatch();
ps2.clearBatch();
}
//ps1.executeBatch(); //执行剩余sql,但是在这里写的话效率较低,因为每次都会调用,实际情况是只需要最后调用一次即可,所以可以单独写一个方法,在测试中的数据满足批处理的全部执行完成之后再调用这个方法 //比如,现在批处理是1000条一次,如果处理9999条数据,则剩余999条不满1000,则不会插入到数据库中,这个时候可以在执行完前9000条数据之后再执行这两句,对此写了个方法,executeRemainderSQL
//ps2.executeBatch(); //同上
}public void executeReminderSQL() throws SQLException{ ps1.executeBatch(); ps1.clearBatch(); ps2.executeBatch(); ps2.clearBatch(); }
}
测试
//Service shenglue
@Test
public void testBatchInsert(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring xml path");
double start = System.currentTimeMillis();
SyslogAlarmService sas = (SyslogAlarmService) ac.getBean("syslogAlarmService");
;i<;i++){//当为1000批处理时,插入一万数据需要一秒左右,十万数据7秒左右,20万数据13秒左右,50万数据31秒左右
Device d = new Device();
d.setId();
Alarm alarm = new Alarm();
alarm.setDevice(d);
//alarm.set
SyslogAlarm sAlarm = new SyslogAlarm();
sAlarm.setAlarm(alarm);
//sAlarm.set
sas.batchInsert(sAlarm);
}sas.executeReminderSQL();//执行剩余的sql
double end = System.currentTimeMillis();
System.+ " 秒");
}
}
使用JDBC批量保存数据(JdbcDaoSupport,JdbcTemplete)的更多相关文章
- JDBC批量插入数据优化,使用addBatch和executeBatch
JDBC批量插入数据优化,使用addBatch和executeBatch SQL的批量插入的问题,如果来个for循环,执行上万次,肯定会很慢,那么,如何去优化呢? 解决方案:用 preparedSta ...
- Jquery Easy UI Datagrid 上下移动批量保存数据
DataGrid with 上下移动批量保存数据 通过前端变量保存修改数据集合,一次性提交后台执行 本想结合easyui 自带的$('#dg').datagrid('getChanges'); 方法来 ...
- springboot jpa 批量保存数据--EntityManager和 JpaRepository
1: 项目里面使用springboo-boot-start-data-jpa操作数据库,通过源码,在repository上继承JpaRepository 可以实现保存操作,其中源码接口为: <S ...
- 使用EntityManager批量保存数据
@PersistenceContext EntityManager em; 从别的系统中定期同步某张表的数据,由于数据量较大,采用批量保存 JPA EntityManager的四个主要方法 ① pub ...
- MySQL:JDBC批量插入数据的效率
平时使用mysql插入.查询数据都没有注意过效率,今天在for循环中使用JDBC插入1000条数据居然等待了一会儿 就来探索一下JDBC的批量插入语句对效率的提高 首先进行建表 create tabl ...
- 【实践】jdbc批量插入数据
参考文献:http://my.oschina.net/u/1452675/blog/203670 http://superjavason.iteye.com/blog/255423 /*测试批量写入数 ...
- JDBC批量插入数据效率分析
对于需要批量插入数据库操作JDBC有多重方式,本利从三个角度对Statement和PreparedStatement两种执行方式进行分析,总结较优的方案. 当前实现由如下条件: 执行数据库:Mysql ...
- jdbc批量插入数据
//插入很多书(批量插入用法) public void insertBooks(List<Book> book) { final List<Book> tempBook=b ...
- Hibernate 批量保存数据
public Boolean save(Collection<Object> os) { int batchSize = 50,i=0; Session session=this.sess ...
随机推荐
- js jquery 实现点击按钮后,倒计时60秒才能再次点击发送验证邮件
<input type="button" id="btn" value="免费获取验证码" /><script type= ...
- LoadRunner脚本实例来验证参数化的取值
LoadRunner脚本实例来验证参数化的取值 SINM {3]!G0问题提出: 主要想试验下,在Controller中,多个用户,多次迭代中参数的取值.51Testing软件测试网(['H5f,d ...
- 如何查看经过编码的cookie?
方法1.去在线工具网站(http://tool.oschina.net/encode?type=2)手动复制编码的cookie,转码后查看. 方法2.用火狐浏览器打开网页,如果有历史记录(存在cook ...
- spark 部署问题
spark的web UI 端口设置:spark-env.sh 中设置SPARK_MASTER_WEBUI_PORT 为自己想设置的端口号. 其他worker 的web UI 端口默认:8081 mas ...
- 【Oracle】ORA-00257:archiver error. Connect internal only, until freed 错误的处理方法
archive log 日志已满ORA-00257: archiver error. Connect internal only, until freed 错误的处理方法 1. 用sys用户登录 s ...
- soapui中文操作手册(十)----REST Sample Project
第一步:打开MockService 1.双击MockService: 2.单击开始mockservice. 你会看到mockservice“端口8080上运行”. 参考: 配置使用MockServic ...
- Storm配置项详解【转】
Storm配置项详解 ——阿里数据平台技术博客:storm配置项详解 什么是Storm? Storm是twitter开源的一套实时数据处理框架,基于该框架你可以通过简单的编程来实现对数据流的实时处理变 ...
- BZOJ 1475 & 1324 && 建图最小割
题意: 给一个矩阵,取其中一方格中的数,满足所有所取方格不相邻. SOL: 典型一个二分图,染色后不相邻的连边即可.跑个最大流,裸裸哒. Code: 代码没什么时间写了...并不是很想贴...都是贴板 ...
- Coder-Strike 2014 - Round 1 C. Pattern
题目的意思是给出n个长度相同的字符串然后找出与他们匹配的字符串 将字符串存入类似二维数组的里面,每一行代表一个字符串,遍历每列,判断每列是否有公共的匹配字符,如果有输出任意一个 如果没有输出'?' # ...
- 洛谷 P1198 [JSOI2008]最大数 Label:线段树
题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度. 2. 插入操作 ...