如何利用JDBC發送SQL語句?
Statement對象用于將SQL語句發送到數據庫中。實際上有三種Statement對象,它們都作為在給定連接上執行SQL語句的包容器:Statement、PreparedStatement(它從Statement繼承而來)和CallableStatement(它從PreparedStatement繼承而來)。它們都專用于發送特定類型的SQL語句:Statement對象用于執行不帶參數的簡單SQL語句;PreparedStatement對象用于執行帶或不帶IN參數的預編譯SQL語句;CallableStatement對象用于執行對數據庫已存儲過程的調用。
Statement接口提供了執行語句和獲取結果的基本方法;PreparedStatement接口添加了處理IN參數的方法;而CallableStatement添加了處理OUT參數的方法。
1. 創建Statement對象
建立了到特定數據庫的連接之后,就可用該連接發送SQL語句。Statement對象用Connection的方法createStatement創建,如下列代碼段中所示:
Connection con = DriverManager.getConnection(url,"sunny",""); Statement stmt = con.createStatement();
為了執行Statement對象,被發送到數據庫的SQL語句將被作為參數提供給Statement的方法:
ResultSet rs = stmt.executeQuery("SELECT a,b,c FROM Table2");
2. 使用Statement對象執行語句
Statement接口提供了三種執行SQL語句的方法:executeQuery、executeUpdate和execute。使用哪一個方法由SQL語句所產生的內容決定。
方法executeQuery用于產生單個結果集的語句,例如SELECT語句。方法executeUpdate用于執行INSERT、UPDATE或DELETE語句以及SQL DDL(數據定義語言)語句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE語句的效果是修改表中零行或多行中的一列或多列。executeUpdate的返回值是一個整數,指示受影響的行數(即更新計數)。對于CREATE TABLE或DROP TABLE等不操作行的語句,executeUpdate的返回值總為零。
執行語句的所有方法都將關閉所調用的Statement對象的當前打開結果集(如果存在)。這意味著在重新執行Statement對象之前,需要完成對當前ResultSet對象的處理。應注意,繼承了Statement接口中所有方法的PreparedStatement接口都有自己的executeQuery、executeUpdate和execute方法。Statement對象本身不包含SQL語句,因而必須給Statement.execute方法提供SQL語句作為參數。PreparedStatement對象并不需要SQL語句作為參數提供給這些方法,因為它們已經包含預編譯SQL語句。
CallableStatement對象繼承這些方法的PreparedStatement形式。對于這些方法的PreparedStatement或CallableStatement版本,使用查詢參數將拋出SQLException。
3. 語句完成
當連接處于自動提交模式時,其中所執行的語句在完成時將自動提交或還原。語句在已執行且所有結果返回時,即認為已完成。對于返回一個結果集的executeQuery方法,在檢索完ResultSet對象的所有行時該語句完成。對于方法executeUpdate,當它執行時語句即完成。但在少數調用方法execute的情況中,在檢索所有結果集或它生成的更新計數之后語句才完成。
有些DBMS將已存儲過程中的每條語句視為獨立的語句;而另外一些則將整個過程視為一個復合語句。在啟用自動提交時,這種差別就變得非常重要,因為它影響什么時候調用commit方法。在前一種情況中,每條語句單獨提交;在后一種情況中,所有語句同時提交。
4. 關閉Statement對象
Statement對象將由Java垃圾收集程序自動關閉。而作為一種好的編程風格,應在不需要Statement對象時顯式地關閉它們。這將立即釋放DBMS資源,有助于避免潛在的內存問題。
5. 使用方法execute
execute方法應該僅在語句能返回多個ResultSet對象、多個更新計數或ResultSet對象與更新計數的組合時使用。當執行某個已存儲過程或動態執行未知SQL字符串(即應用程序程序員在編譯時未知)時,有可能出現多個結果的情況,盡管這種情況很少見。例如,用戶可能執行一個已存儲過程,并且該已存儲過程可執行更新,然后執行選擇,再進行更新,再進行選擇,等等。通常使用已存儲過程的人應知道它所返回的內容。
因為方法execute處理非常規情況,所以獲取其結果需要一些特殊處理并不足為怪。例如,假定已知某個過程返回兩個結果集,則在使用方法execute執行該過程后,必須調用方法getResultSet獲得第一個結果集,然后調用適當的getXXX方法獲取其中的值。要獲得第二個結果集,需要先調用getMoreResults方法,然后再調用getResultSet方法。如果已知某個過程返回兩個更新計數,則首先調用方法getUpdateCount,然后調用getMoreResults,并再次調用getUpdateCount。
對于不知道返回內容,則情況更為復雜。如果結果是ResultSet對象,則方法execute返回true;如果結果是Javaint,則返回false。如果返回int,則意味著結果是更新計數或執行的語句是DL命令。在調用方法execute之后要做的第一件事情是調用getResultSet或getUpdateCount。調用方法getResultSet可以獲得兩個或多個ResultSet對象中第一個對象;或調用方法getUpdateCount可以獲得兩個或多個更新計數中第一個更新計數的內容。
當SQL語句的結果不是結果集時,則方法getResultSet將返回null。這可能意味著結果是一個更新計數或沒有其它結果。在這種情況下,判斷null真正含義的唯一方法是調用方法getUpdateCount,它將返回一個整數。這個整數為調用語句所影響的行數;如果為-1則表示結果是結果集或沒有結果。如果方法getResultSet已返回null(表示結果不是ResultSet對象),則返回值-1表示沒有其它結果。也就是說,當下列條件為真時表示沒有結果(或沒有其它結果):
((stmt.getResultSet()==null)&&(stmt.getUpdateCount()==-1))
如果已經調用方法getResultSet并處理了它返回的ResultSet對象,則有必要調用方法getMoreResults以確定是否有其它結果集或更新計數。如果getMoreResults返回true,則需要再次調用getResultSet來檢索下一個結果集。如上所述,如果getResultSet返回null,則需要調用getUpdateCount來檢查null是表示結果為更新計數還是表示沒有其它結果。
當getMoreResults返回false時,它表示該SQL語句返回一個更新計數或沒有其它結果。因此需要調用方法getUpdateCount來檢查它是哪一種情況。在這種情況下,當下列條件為真時表示沒有其它結果:
((stmt.getMoreResults()==false)&&(stmt.getUpdateCount()==-1))
下面的代碼演示了一種方法用來確認已訪問調用方法execute所產生的全部結果集和更新計數:
stmt.execute(queryStringWithUnknownResults); while(true){ introwCount=stmt.getUpdateCount(); if(rowCount>0){//它是更新計數 System.out.println("Rows changed="+count); stmt.getMoreResults(); continue; } if(rowCount==0){//DDL命令或0個更新 System.out.println("No rows changed or statement was DDL command"); stmt.getMoreResults(); continue; } //執行到這里,證明有一個結果集 //或沒有其它結果 ResultSet rs=stmt.getResultSet(); if(rs!=null){ ...//使用元數據獲得關于結果集列的信息 while(rs.next()){ ...//處理結果 stmt.getMoreResults(); continue; } break;//沒有其它結果 |
|