From Gossip@Openhome

Java Gossip: Statement、 ResultSet

Connection物件是代表Java與資料庫的連線,接下來我們要執行SQL的話,必須取得 Statement物件,它代替您執行SQL敘述並取得執行之後的結果,您可以使用Connection的createStatement()來建立Statement物件
Connection conn = DriverManager.getConnection(
                           url, user, password);
Statement stmt = conn.createStatement();
 
取得Statement物件之後,我們可以使用executeUpdate()、executeQuery()等方法來執行 SQL,executeUpdate()主要是用來執行CREATE TABLE、INSERT、DROP TABLE、ALTER TABLE等會改變資料庫內容的SQL,例如:
stmt.executeUpdate("INSERT INTO message VALUES('良葛格', " +
           "'caterpillar@mail.com', '留言吧', '2004-5-26'," +
           "'到此一遊')");
 
executeQuery()方法則是用於SELECT等查詢資料庫的SQL,executeUpdate()與 executeQuery()都會傳回ResultSet物件,代表變更或查詢的結果,查詢的結果會是一筆一筆的資料,您使用next()來移動至下一筆資料,它會傳回 true 或 false表示是否有下一筆資料,接著可以使用getXXX()來取得資料,例如getString()、getFloat()、getDouble()等方法,分別取得相對應的欄位型態資料,getXXX()方法都提供有依欄位名稱取得資料,或是依欄位順序取得資料的方法,一個例子如下,您指定欄位名稱來取得資料:
ResultSet result =
              stmt.executeQuery("SELECT * FROM message");
while(result.next()) {
    System.out.print(result.getString("name") + "\t");
    System.out.print(result.getString("email") + "\t");
    System.out.print(result.getString("subject") + "\t");
    System.out.print(result.getString("time") + "\t");
    System.out.println(result.getString("memo") + "\t");
}
 

使用查詢到的結果之欄位順序來顯示結果的方式如下:
ResultSet result =
              stmt.executeQuery("SELECT * FROM message");
while(result.next()) {
    System.out.print(result.getString(1) + "\t");
    System.out.print(result.getString(2) + "\t");
    System.out.print(result.getString(3) + "\t");
    System.out.print(result.getString(4) + "\t");
    System.out.println(result.getString(5) + "\t");
}
 
Statement的execute()可以用來執行SQL,並可以測試所執行的SQL是執行查詢或是更新,傳回 true的話表示SQL執行將傳回ResultSet表示查詢結果,此時可以使用getResultSet()取得ResultSet物件,如果 execute()傳回false,表示SQL執行會傳回更新筆數或沒有結果,此時可以使用getUpdateCount()取得更新筆數。如果事先無法 得知是進行查詢或是更新,就可以使用execute()。

下面的程式是個完整的範例,注意我們在查詢結束後,可以使用Statement的close()方法來釋放Statement的資料庫資源與JDBC資源,而最後不使用連線時也使用Connection的close()來關閉連線:

  • DBTest.java
package onlyfun.caterpillar;

import java.sql.*;

public class DBTest {
public static void main(String[] args) {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/GUESTBOOK?" +
"useUnicode=true&characterEncoding=Big5";
String user = "caterpillar";
String password = "123456";

Connection conn = null;
Statement stmt = null;

try {
Class.forName(driver);
conn = DriverManager.getConnection(
url, user, password);
stmt = conn.createStatement();

stmt.execute("INSERT INTO message VALUES('良葛格" +
"', 'caterpillar@mail.com', '留言吧', "+
"'2004-5-26', '到此一遊')");

ResultSet result = stmt.executeQuery(
"SELECT * FROM message");
while(result.next()) {
System.out.print(result.getString(1) + "\t");
System.out.print(result.getString(2) + "\t");
System.out.print(result.getString(3) + "\t");
System.out.print(result.getString(4) + "\t");
System.out.println(result.getString(5) + "\t");
}
}
catch(ClassNotFoundException e) {
System.out.println("找不到驅動程式");
e.printStackTrace();
}
catch(SQLException e) {
e.printStackTrace();
}
finally {
if(stmt != null) {
try {
stmt.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}
}
}

最後注意到的是,Connection物件預設為自動「認可」(Commit),也就是Statement執行SQL敘述完 後,馬上對資料庫進行操作變更,如果想要對Statement要執行的SQL進行除錯,可以使用setAutoCommit(false)來將自動認可取 消,在執行完SQL之後,再呼叫Connection的commit()方法認可變更,使用Connection的getAutoCommit()可以測 試是否設定為自動認可。

不過無論是否有無執行commit()方法,只要SQL沒有錯,在關閉Statement或Connection前,都會執行認可動作,對資料庫進行變 更。