更新時(shí)間:2023-05-23 來源:黑馬程序員 瀏覽量:
在實(shí)際開發(fā)中,經(jīng)常需要向數(shù)據(jù)庫發(fā)送多條SQL語句,這時(shí),如果逐條執(zhí)行這些SQL語句,效率會(huì)很低。為此,JDBC提供了批處理機(jī)制,即同時(shí)執(zhí)行多條SQL語句。Statement和PreparedStatement都實(shí)現(xiàn)了批處理,本節(jié)將針對(duì)它們的批處理方式進(jìn)行詳細(xì)的講解。
1.Statement批處理
當(dāng)向數(shù)據(jù)庫發(fā)送多條不同的SQL語句時(shí),可以使用Statement實(shí)現(xiàn)批處理。Statement通過addBatch()方法添加一條SQL語句,通過executeBatch()方法批量執(zhí)行SQL語句。為了幫助讀者更好地學(xué)習(xí)如何使用Statement實(shí)現(xiàn)批處理,下面通過一個(gè)案例來演示。
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sgl.Statement; import cn.itcast.jdbc.example.utils.JDBCUtils; public class Example10 { public static void main (String[] args) { connection conn=null: statement stmt=null; try { //加載數(shù)據(jù)庫驅(qū)動(dòng) conn= JDBCUtils.getConnection(): stmt*conn.createStatement(); //SQL語句 String sql1="DROP TABLE IF EXISTS school"; String sq12="CREATE TABLE school (id int,name varchar(20))"; String sql3="INSERT INTO school VALUES(2,'傳智播客')"; String sql4="UPDATE school SET id=1"; //Statement 批處理 SQL語句 stmt.addBatch(aql1); stmt.addBatch (sql2): stmt.addBatch(sql3); stmt.addBatch (sq14); stmt.executeBatch(); } catch (Exception e) { e.printStackTrace(); } finally{ //釋放資源 JDBCUtils.release (null,stmt,conn); } } }
程序運(yùn)行過程中,Statement會(huì)將4條SQL語句提交給數(shù)據(jù)庫一起執(zhí)行。為了驗(yàn)證例1-13中的SQL語句是否執(zhí)行成功,進(jìn)入MySQL,使用SELECT語句查看school表,JhmSQI嘉句的執(zhí)行結(jié)果如下所示。
mysql>select · from school; +------+--------------+ | id | name | +------+--------------+ | 1 | 傳智播客 | +------+--------------+ 1 row in set (0.00 sec)
從上述結(jié)果可以看出,school表存在,并且向表中添加了一條數(shù)據(jù),該數(shù)據(jù)的id被成功修改成了1。
2. PreparedStatement 批處理
當(dāng)向同一個(gè)數(shù)據(jù)表中批量更新數(shù)據(jù)時(shí),如果使用Sratement,需要書寫很多SQL語句,這時(shí),為了避免重復(fù)代碼的書寫,可以使用PreparedStatement 實(shí)現(xiàn)批處理。與Statement相比,PreparedStatement靈活許多,它既可以使用完整的SQL,也可以使用帶參數(shù)的不完整SQL。但是,對(duì)于不完整的SQL,其具體的內(nèi)容是采用“?”占位符形式出現(xiàn)的,設(shè)置時(shí)要按照“?”順序設(shè)置具體的內(nèi)容。
為了幫助讀者更好地學(xué)習(xí)如何使用PreparedStatement實(shí)現(xiàn)批處理,下面通過一個(gè)案例來演示。
package cn.itcast.jdbc.example; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement ; import cn.itcast.jdbc.example.utils.JDBCUtils; public class Exanple11 { public static void main (String[] args) { Connection conn=null; PreparedStatement preStmt=null; try { //加載并注冊(cè)數(shù)據(jù)庫驅(qū)動(dòng) conn=JDBCUtils.getConnection(): String sql="INSERT INTO users(name,password,email,birthday)" +"VALUES(?,?,?,?)"; preStmt=conn.prepareStatement(sq1); for (int i=0;i<5;i++)( preStmt.setString(1, "name"+i); preStmt.setString(2,"password"+i); preStmt.setString(3,"email"+i+"9itcast.cn"); preStmt.setDate(4, Date.valueOf("1989-02-19")); preStmt.addBatch(); } preStmt.executeBatch(): } catch (Exception e) { e.printStackTrace(); } finally{ //釋放資源 JDBCUtils.release (null, preStmt, conn); } } }
程序運(yùn)行后,users表中會(huì)同時(shí)添加5條數(shù)據(jù)。為了查看數(shù)據(jù)添加是否成功,進(jìn)入MySQL,使用SELECT語句查看 users表,結(jié)果如下所示。
mysql>select * from users; +-----+-----------+------------+--------------------+--------------+ |id | name | password | email | birthday | +-----+-----------+------------+--------------------+--------------+ | 1 | za | 123456 | zs@sina.com | 1980-12-04 | | 2 | lisi | 123456 | lisi@sina.com | 1981-12-04 | | 3 | wangwu | 123456 | wangwu@sina.com | 1979-12-04 | | 5 | hl | 123 | hl@sina.com | 2015-04-18 | | 6 | name0 | password0 | email0@itcast.cn | 1989-02-19 | | 7 | name1 | password1 | email1@itcast.cn | 1989-02-19 | | 8 | name2 | password2 | email2@itcast.cn | 1989-02-19 | | 9 | name3 | password3 | email3@itcast.cn | 1989-02-19 | | 10 | name4 | password4 | email4@itcast.cn | 1989-02-19 | +-----+-----------+------------+--------------------+--------------+ 9 rows in set (0.00 sec)
從上述結(jié)果可以看出,Examplel1批量添加了5條數(shù)據(jù)。由此可見,當(dāng)向同一個(gè)表中批量添加或者更新數(shù)據(jù)的時(shí)候,使用PreparedStatement比較方便。
注意:批處理執(zhí)行SELECT語句會(huì)報(bào)錯(cuò)。因?yàn)镾tatement和 PreparedStatement的executeBatch()方法的返回值都是int[]類型,所以,能夠進(jìn)行批處理的SQL語句必須是INSERT、UPDATE、DELETE等返回值為int類型的SQL語句。