什麼是批處理?
- 當需要向數據庫中插入大批量數據時,在批處理之前,要執行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);
}
}
}