业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。
实现批处理有两种方式,第一种方式:如果有100条sql语句,调用addBatch(sql)
方法时,就会把sql语句加到list集合里去
Statement.addBatch(sql) list
执行批处理SQL语句:
executeBatch()方法:执行批处理命令
clearBatch()方法:清除批处理命令
练习
连接数据库的代码我就不细述了,前面文章里都有。
@Test
public void test1() {
Connection conn = null;
//用Statement去做
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql1 = "insert into testbatch(id,name) values('1','aaa')";
String sql2 = "update testbatch set name='bbb' where id='1'";
st = conn.createStatement();
st.addBatch(sql1);
st.addBatch(sql2);
//返回int[] 第一条sql影响数据库几行,第二条sql影响数据库几行
st.executeBatch();
//发给数据库之后,就要清理批处理
st.clearBatch();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.release(conn, st, rs);
}
}
结果就是将id
为1的name
更改为了bbb
。
第二种方式:
用PreparedStatement 语句时只能向数据库发送一条sql语句,只是可以做批量数据的处理。而第一种方式可以发送不同的sql语句。
实际开发里,这种方式用的比较多。
@Test
public void test2() {
Connection conn = null;
//用Statement去做
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into testbatch(id,name) values(?,?)";
ps = conn.prepareStatement(sql);
/*
//1
ps.setString(1,"2");
ps.setString(2,"qwer");
ps.addBatch();
//2
ps.setString(1,"3");
ps.setString(2,"asdf");
ps.addBatch();
*/
//换用for循环实现
for (int i = 1; i <= 10; i++) {
ps.setString(1, i + "");
ps.setString(2, "aa" + i);
ps.addBatch();
}
//返回int[] 第一条sql影响数据库几行,第二条sql影响数据库几行
ps.executeBatch();
//发给数据库之后,就要清理批处理
ps.clearBatch();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
注意:如果for循环里的i<=10000000
,就意味着一次性要插入1000万条数据,会报java.lang.OutOfMemoryError:Java heap space,超出内存空间。所以1000万条数据就不能这样插入,而是采取1000条1000条的插入(每1000条做一个批处理)。改动后的代码如下:
@Test
public void test2() {
Connection conn = null;
//用Statement去做
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into testbatch(id,name) values(?,?)";
ps = conn.prepareStatement(sql);
//换用for循环实现
for (int i = 1; i <= 10; i++) {
ps.setString(1, i + "");
ps.setString(2, "aa" + i);
ps.addBatch();
if (i % 1000 == 0) {
//返回int[] 第一条sql影响数据库几行,第二条sql影响数据库几行
ps.executeBatch();
//发给数据库之后,就要清理批处理
ps.clearBatch();
}
}
ps.executeBatch();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.release(conn, ps, rs);
}
}
MySQL插入1000万条数据大概要3个多小时。oracle就只需要6分多钟。