ITEEDU

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前,都会执行认可动作,对数据库进行变 更。