什么是批处理?
- 当需要向数据库中插入大批量数据时,在批处理之前,要执行100条sql,就只需100此打开连接关闭连接和网络传输。
- 批处理过程:将大量的SQL打包成一个批次,发送给服务器,服务器接收数据,打开批,一次执行批里的sql,这样减少与数据库的交互,提高程序的效率。
- 如何实现批处理?
实现方式一:Statement对象实现
需求:利用statement开发,插入dept表,100条
实现方式二:Preparedstatement对象实现
需求:利用preparedstatement对象,向dept表中插入100条数据
开发步骤:
- 1.获取数据库连接
- 2.获取传输器
- 3.执行SQL(批处理,打成一个批次,统一发给服务器)
- 4.解析结果集
- 5.关闭资源
注意:每次利用批处理完成插入100条数据,打一个批次是,要统一发送数据
事务优化
需求:让批处理程序快一点
设置事务的开关:conn.setAutoCommit(false);
手动提交事务:conn.commit();
两种方式的区别:
- Statement
* 优点:在一次批处理中,SQL更加灵活
* 缺点:发生SQL注入,效率低,拼接参数麻烦
- preparedstatement
* 优点:防止SQL注入,提高执行效率(骨架缓存),占位符拼接参数
* 缺点:在一次批处理中,只可以完成骨架相同的SQL
- 总结:
** 在没使用批处理时,插入100条SQL的话,需要打开100次数据库连接并且需要100次网络传输。
** 使用了批处理,效率不一定就高,跟数据库的版本,驱动的版本,硬件配置,网络速度都有关系
** 使用jdbc批处理时建议结合着事务优化一起做
** 注意:不建议一次性向批中插入大量数据,会造成OutofMemory
代码实现如下:
package on.tedu.batch_批处理;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import on.tedu.Util_工具类.JDBCUtils;
/**
* 这个类用来完成批处理
* 开发步骤:
* 1.获取数据库连接
* 2.获取传输器
* 3.执行SQL(批处理,打成一个批次,统一发给服务器)
* 4.解析结果集
* 5.关闭资源
* 两种方式的区别
* 1.Statement
* 优点:在一次批处理中,SQL更加灵活
* 缺点:发生SQL注入,效率低,拼接参数麻烦
*
* 2.perparedstatement
* 优点:防止SQL注入,提高执行效率(骨架缓存),占位符拼接参数
* 缺点:在一处批处理中,只可以完成骨架相同的SQL
* 总结:
* 在没使用批处理时,插入100条SQL的话,需要打开100此数据库连接并且需要100此网络传输
* 使用了批处理,效率不一定就高,跟数据库的版本,驱动的版本,硬件配置,网络速度都有关系
* 使用jdbc批处理时建议结合着事务处理优化一起做
* 注意:不建议一次性向批中插入大量数据,会造成OutofMenory
* @date 2018年3月26日
*
*/
public class StatementBatch {
@Test//单元测试
public void statementBatch(){
Connection conn = null;
Statement st =null;
ResultSet rs =null;
try {
//1.获取数据库连接
conn = JDBCUtils.getConnection();
//2.获取传输器对象
st=conn.createStatement();
//3.执行SQL(批处理,打成一个批次,统一发给服务器)
int rows=0;
for(int i=0;i<100;i++){
//普通插入100条数据的方法
//rows =st.executeUpdate("insert into dept values(null,'"+i+"')");
//利用批处理完成插入100条数据
//并打一个批次
st.addBatch("insert into dept values(null,'"+i+"')");
}
//统一把SQL发送给服务器
st.executeBatch();
System.out.println(rows);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCUtils.close(conn, st, rs);
}
}
@Test//插入数据 最终版
public void PSBatch(){
Connection conn=null;
PreparedStatement ps =null;
try {
//1.获取数据库连接
conn =JDBCUtils.getConnection();
//设置数据的开关 - 把默认事务关闭 --非常关键
conn.setAutoCommit(false);
long start =System.currentTimeMillis();
//2.获取传输器对象
//3.执行SQL
String sql ="insert into dept values(null,?)";
ps=conn.prepareStatement(sql);//传入骨架
//设置参数
for(int i=0;i<100;i++){
ps.setString(1, "ps"+i);//这里的i代表的是一个?号
//把SQL添加到一个批次中
ps.addBatch();//这里添加到批次里
}
//统一把SQL发给服务器
int[] rows = ps.executeBatch();//这里返回一个int[],意识是影响了一行,就会得到一个数字
//手动提交事务
conn.commit();
long end = System.currentTimeMillis();
System.out.println(rows.length);
System.out.println("-----------"+(end-start)+"-----------");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//5关闭资源,这里直接传子类对象,后面rs没有,就直接传null
JDBCUtils.close(conn, ps, null);
}
}
}