這兩個對象的區別:
1.Statement它更適合執行不同sql的批處理,它沒有提供預處理功能,性能比較低。
2.PreparedStatement它適合執行相同的批處理,它提供了預處理功能,屬性比較高。
/**
*
@param args
*
@throws SQLException
*
@throws ClassNotFoundException
*/
public
static
void main(String[] args)
throws ClassNotFoundException,
SQLException {
// 定義sql 語句
String sql1 = "create table person(id int,name varchar(20))";
String sql2 = "insert into person values(1,'tom')";
String sql3 = "insert into person values(2,'fox')";
String sql4 = "insert into person values(3,'tony')";
String sql5 = "update person set name='張三' where id=1";
String sql6 = "delete from person where id=3";
Connection conn = jdbcUtils.
getConnection();
Statement st = conn.createStatement();
// 添加批處理sql
st.addBatch(sql1);
st.addBatch(sql2);
st.addBatch(sql3);
st.addBatch(sql4);
st.addBatch(sql5);
st.addBatch(sql6);
// 執行批處理sql
st.executeBatch();
st.clearBatch();
st.close();
conn.close();
}
使用版本高一點的 jdbc的jar包時加入參數可開啟緩存在url中加參數:
?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
/**
*
@param args
*
@throws SQLException
*
@throws ClassNotFoundException
*/
public
static
void main(String[] args)
throws ClassNotFoundException,
SQLException {
String sqlString = "insert into person values(?,?)";
Connection conn = jdbcUtils.
getConnection();
PreparedStatement pst = conn.prepareStatement(sqlString);
long l = System.
currentTimeMillis();
for (
int i = 0; i < 10000; i++) {
pst.setInt(1, i);
pst.setString(2, "name" + i);
pst.addBatch();
if (i % 1000 == 0) {
pst.executeBatch();
pst.clearBatch(); // 清空緩存
}
}
pst.executeBatch();
pst.close();
conn.close();
System.
out.println(System.
currentTimeMillis() - l);
}
方法:
-
public static Connection getConnection(){
-
try {
-
Class.forName( "com.mysql.jdbc.Driver");
-
ct = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/test","squirrel","xiaoyang");
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return ct;
-
}
-
-
/**釋放數據庫鏈接資源:注意數據庫資源關閉的順序*/
-
public static void closeConnection(){
-
-
try { //注意關閉數據庫資源的先后順序
-
if(rs!=null){
-
rs.close();
-
} if(ps!=null){
-
ps.close();
-
} if(ct!=null){
-
ct.close();
-
}
-
} catch (SQLException e) {
-
e.printStackTrace();
-
}
-
}
-
測試方法:
-
/**
-
* PreparedStatement批量執行sql
-
*/
-
public static void excuteBatchInsertDatabase(){
-
-
ct=getConnection();
-
-
try {
-
ct.setAutoCommit( false);
-
ps=ct.prepareStatement( "insert into user(name,passwd,age,gender) values(?,?,?,?)");
-
-
ps.setString( 1, "BBBB");
-
ps.setString( 2, "BBBB");
-
ps.setInt( 3, 20);
-
ps.setString( 4, "F");
-
ps.addBatch();
-
-
ps.setString( 1, "BBBB");
-
ps.setString( 2, "BBBB");
-
ps.setInt( 3, 20);
-
ps.setString( 4, "F");
-
ps.addBatch();
-
-
/**
-
* 等價於sql語句:
-
* insert into user(name,passwd,age,gender) values
-
* ("BBBB","BBBB",20,'F'),
-
* ("BBBB","BBBB",20,'F');
-
*/
-
ps.executeBatch(); //批量執行sql,避免因此單次的insert操作建立多個Connection浪費資源
-
ct.commit();
-
} catch (Exception e) {
-
e.printStackTrace();
-
try {
-
ct.rollback();
-
} catch (SQLException e1) {
-
e1.printStackTrace();
-
}
-
} finally{
-
closeConnection();
-
}
-
}
執行excuteBatchInsertDatabase()方法數據庫記錄:
數據庫數據記錄表明:sql語句批量執行成功
注意:
批量查詢最好交由一個事務組控制,如果出現操作異常可以進行事務回滾,不至於造成部分數據更新部分數據更新失敗的尷尬局面,避免你臟數據污染數據庫
- 由於 PreparedStatement 對象已預編譯過,所以其執行速度要快於 Statement 對象。因此,多次執行的 SQL 語句經常創建為 PreparedStatement 對象,以提高效率
- Statement用於執行靜態的sql語句
-
由於PreparedStatement創建對象消耗資源比較高,所以只執行 一次的sql語句,不使用PreparedStatement
- 主要目的減少執行計划次數,防止sql注入
- jdbc 元數據 meta ,ResultSet.xxx
- Mysql jdbc 關閉自動提交事務 可提升性能 conn.setAutoCommit(false) ,
- 歸還conn時 須提前設置為.setAutoCommit(true)
- rollback()回滾
- 批量處理:一次向數據庫發送多個SQL語句時,可以減少通信開銷,從而提高性能。