JDBC编程

 

JDBC API 架构图如下:

 

<!---->1.    <!---->JDBC 驱动程序类型

  • <!----> <!---->Type 1 JDBC-ODBC Bridge
    使用者的电脑上必须事先安装好ODBC 驱动程式,Type 1 驱动程式利用Bridge 的方式将JDBC 的呼叫方式转换为ODBC 的呼叫方式,用于Microsoft Access 之类的资料库存取:
    Application <--> JDBC-ODBC Bridge <--> ODBC Driver <--> Database

  • <!----> <!---->Type 2 Native-API Bridge
    驱动程式上层包装Java 程式以与Java 应用程式作沟通,将JDBC 呼叫转为原生程式码的呼叫,下层为原生语言(像是CC++ )来与资料库作沟通,下层的函式库是针对特定资料库设计的,不若Type 1 可以对ODBC 架构的资料库作存取:
    Application <--> Native-API Bridge <--> Native Driver <--> Database

  • <!----> Type 3 JDBC-middleware
    透过中间件来存取资料库,使用者不必安装特定的驱动程式,而是由驱动程式呼叫中间件,由中间件来完成所有的资料库存取动作,然后将结果传回给驱动程式:
    Application <--> JDBC-middleware <--> middleware <--> Database

  • Type 4 Pure Java Driver
    使用纯Java 撰写驱动程式与资料库作沟通,而不透过桥接或中间件来存取资料库:
    Application <--> Pure Java Driver <--> Database

下面有一个简单的JDBC 测试示例:

首先把数据库连接信息放到一个配置文件里:

 

jdbc.drivers = com.mysql.jdbc.Driver
jdbc.url
= jdbc:mysql://localhost:3306/jdbc?useUnicode=true&amp;characterEncoding=utf8
jdbc.username
= root
jdbc.password
= ******

 

然后示例代码从中读取信息并测试连接:

package cn.janwer.jdbc;

import java.sql.*;
import java.io.*;
import java.util.*;

public class TestDB {
	public static void main(String args[]) {
		try {
			runTest();
		} catch (SQLException ex) {
			while (ex != null) {
				ex.printStackTrace();
				ex = ex.getNextException();
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * Runs a test by creating a table, adding a value, showing the table
	 * contents, and removing the table.
	 */
	public static void runTest() throws SQLException, IOException {
		Connection conn = getConnection();
		try {
			Statement stat = conn.createStatement();

			stat.execute("CREATE TABLE Greetings (Message CHAR(20))");
			stat.execute("INSERT INTO Greetings VALUES ('Hello, World!')");

			ResultSet result = stat.executeQuery("SELECT * FROM Greetings");
			result.next();
			System.out.println(result.getString(1));
			stat.execute("DROP TABLE Greetings");
		} finally {
			conn.close();
		}
	}

	/**
	 * Gets a connection from the properties specified in the file
	 * database.properties
	 * 
	 * @return the database connection
	 */
	public static Connection getConnection() throws SQLException, IOException {
		Properties props = new Properties();
		FileInputStream in = new FileInputStream("./src/cn/janwer/jdbc/database.properties");
		props.load(in);
		in.close();

		String drivers = props.getProperty("jdbc.drivers");
		if (drivers != null)
			System.setProperty("jdbc.drivers", drivers);
		String url = props.getProperty("jdbc.url");
		String username = props.getProperty("jdbc.username");
		String password = props.getProperty("jdbc.password");

		return DriverManager.getConnection(url, username, password);
	}
}

 2.   执行 SQL 命令

在执行SQL 命令之前,首先需要创建一个Statement 对象。要创建statement 对象,需要使用调用DriverManager.getConnection 方法所获得的Connection 对象。

Statement stat = conn.createStatement();

接着,将要执行的SQl 语句放入字符串中,例如:

String command = “UPDATE books SET Price = Price – 5.00 WHERE Title NOT LIKE ‘%Introduction%’;

然后,调用 Statement 类中的 executeUpdate 方法:

Stat.executeUpdate(command);

executeUpdate() 方法将返回受SQL 命令影响的行数。executeUpdate() 主要是用来执行CREATE TABLEINSERTDROP TABLEALTER TABLE 等会改变资料库内容的SQL 。但是,执行SELECT 查询时必须使用executeQuery 方法。

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()

 

注意: Connection 物件预设为自动 认可 Commit 也就是Statement 执行SQL 叙述完后,马上对资料库进行操作变更,如果想要对Statement 要执行的SQL 进行除错,可以使用 setAutoCommit(false) 来将自动认可取消,在执行完SQL 之后,再呼叫Connectioncommit() 方法认可变更,使用ConnectiongetAutoCommit() 可以测试是否设定为自动认可。

不过无论是否有无执行 commit() 方法,只要SQL 没有错,在关闭StatementConnection 前,都会执行认可动作,对资料库进行变更。

 

API   java.sql.DriverManager

static Connection getConnection(String url, String user, String password)

建立一个到指定数据库的连接,并返回一个Connection 对象。

 

API   java.sql.Connection

Statement createStatement()

创建一个Statement 对象,用以执行不带参数的SQL 查询和更新。

void close()

用于立即关闭当前的连接以及释放由它所创建的JDBC 资源

 

API   java.sql.Statement

ResultSet executeQuery(String sqlQuery)

执行给定字符串中的SQL 语句,并返回一个用于查看查询结果的ResultSet 对象。

int executeUpdate(String sqlStatement)

执行字符串中指定的 INSERT,UPDATE DELETE SQL 语句。还可以执行数据库义语句(DLL )的语句,如 CREATE TABLE 。返回受影响的记录总数,如果是没有更新计数的语句,则返回-1

boolean execute(String sqlStatement)

执行字符串中指定的 SQL 语句。如果该语句返回一个结果集则该方法返回 true ; 反之,反之,返回 false 。使用 getResultSet getUpdateCount 方法可以得到语句的执行结果。

int getUpdateCount()

返回受前一条更新语句影响的记录总数。如果前一条语句未更新数据库,则返回-1 。对于每一条执行过的语句,该方法只能调用一次。

ResultSet getResultSet()

返回前一条查询语句的结果集。如果前一条语句未产生结果集,则返回null 值。对于每一条执行过的语句,该方法只能被调用一次。

void close()

关闭Statement 对象以及它所对应的结果集。

 

API   java.sql.ResultSet

boolean next()

将结果集中的当前行向前移动一行。如果已经到达最后一行的后面,则返回 false 。注意,初始情况下必然调用该方法才能转到第一行。

int findColumn(String columnName)

根据给定的列名,返回该列的序号。

void close()

立即关闭当前的结果集。

 

API   java.sql.SQLException

String getSQLState()

返回“SQL 状态”,它是一个与错误有关的5 位数的错误编码。

int getErrorCode()

返回与数据库供应商相关的异常编码

SQLException getNextException()

返回链接到该SQLException 对象的下一个异常,该异常可能包含更多的错误信息

 

<!---->3.     <!---->预编译查询语句

Statement 主要用于执行静态的SQL 陈述,也就是在执行 executeQuery() , executeUpdate() 等方法时,指定内容固定不变的SQL 语句字串,每一句SQL 只适用于当时的执行,如果您有些操作只是SQL 语句当中某些参数会有所不同,其余的SQL 子句皆相同,则您可以使用 java.sql.PreparedStatement

 

您可以使用ConnectionpreparedStatement() 方法建立好一个预先编译(precompile )的SQL 语句,当中参数会变动的部份,先指定"?" 这个占位字元,例如:

PreparedStatement stmt = conn.prepareStatement("INSERT INTO message VALUES(?, ?, ?, ?, ?)");

要将参数指定给每一个栏位,我们可以使用setInt()setString() 等等方法,例如:

stmt.setString(1, " 米小狗 ");
stmt.setString(2, "[email protected]");
stmt.setString(3, "
留言吧 ");
stmt.setString(4, "2008-4-16");
stmt.setString(5, "
到此一游 ");
stmt.executeUpdate();
stmt.clearParameters();

setXXX() 方法的第一个参数指定 ? 的位置,而第二个参数为要加入至资料表栏位的值,要让SQL 执行生效,要执行 executeQuery() executeUpdate() 方法,使用 setXXX() 来设定的参数会一直有效,可以于下一次使用,如果想要清除设定好的参数,可以执行clearParameters() 方法。

使用PreparedStatement 也可以进行批次处理,直接来看个例子就知道如何使用:

PreparedStatement stmt = conn.prepareStatement("INSERT INTO Users VALUES(?,?, ?)");
 
User[] users = ...;

for(int i=0; i<users.length; i++) {
     stmt.setInt(1, users[i].getID());
     stmt.setString(2, users[i].getName());
     stmt.setString(3, users[i].getPassword());
     stmt.addBatch( );
}
 
stmt.executeBatch(); 

API   java.sql.Connection

PreparedStatement prepareStatement(String sql)

返回一个含预编译语句的PreparedStatement 对象。字符串SQL 代表了一个SQL 语句,该语句可以包含一个或多个由“?” 指明的参数占位符。

 

API   java.sql.PreparedStatement

void setXxx(int n, Xxx x)

(Xxx int double String Date 之类的数据类型 ) 设置第 n 个参数值为 x

void clearParameters()

清除预备语句中的所有当前参数

ResultSet executeQuery()

执行预备SQL 查询,并返回一个ResultSet 对象

int executeUpdate()

执行预备SQL 语句INSERTUPDATEDELETE , 这些语句由PreparedStatement 对象表示。该方法返回在执行上述语句过程中所有受影响的记录总数;如果执行的是数据定义语言中(DLL) 的语句,如CREATE TABLE, 则该方法返回0

你可能感兴趣的:(sql,编程,mysql,中间件,jdbc)