JDBC 入门:基础步骤、示例与实用工具
1. 使用 JDBC 的基本步骤
在 Java 开发中,JDBC(Java Database Connectivity)是用于与数据库进行交互的标准 API。使用 JDBC 进行数据库操作,通常需要遵循以下几个基本步骤:
1. 加载 JDBC 驱动 :
要使用 JDBC 连接数据库,首先需要加载相应的 JDBC 驱动。可以使用 Class.forName 方法,传入驱动的全限定类名来加载驱动。由于该方法可能会抛出 ClassNotFoundException 异常,因此需要将其放在 try/catch 块中。示例代码如下:
try {
Class.forName("connect.microsoft.MicrosoftDriver");
Class.forName("oracle.jdbc.driver.OracleDriver");
Class.forName("com.sybase.jdbc.SybDriver");
} catch(ClassNotFoundException cnfe) {
System.err.println("Error loading driver: " + cnfe);
}
大多数数据库厂商会为其数据库提供免费的 JDBC 驱动,同时也有许多第三方厂商为旧数据库提供驱动。可以访问 http://java.sun.com/products/jdbc/drivers.html 获取最新的驱动列表。很多驱动厂商还提供免费试用版本,方便在不付费的情况下学习 JDBC。需要注意的是,大多数 JDBC 驱动以 JAR 文件形式分发,因此要确保在 CLASSPATH 设置中包含 JAR 文件的路径。
2. 定义连接 URL :
加载驱动后,需要指定数据库服务器的位置。数据库连接 URL 使用 jdbc: 协议,其中包含服务器主机、端口和数据库名称等信息。不同数据库的 URL 格式可能不同,具体格式可参考相应驱动的文档。以下是 Oracle 和 Sybase 数据库的示例:
String host = "dbhost.yourcompany.com";
String dbName = "someName";
int port = 1234;
String oracleURL = "jdbc:oracle:thin:@" + host + ":" + port + ":" + dbName;
String sybaseURL = "jdbc:sybase:Tds:" + host + ":" + port + ":" + "?SERVICENAME=" + dbName;
如果从 applet 中使用 JDBC,由于浏览器为防止恶意 applet 绕过企业防火墙,会限制 applet 只能与加载它的服务器进行网络连接。因此,若要在 applet 中使用 JDBC,数据库服务器需与 HTTP 服务器位于同一台机器上,或者使用代理服务器将数据库请求重定向到实际服务器。
3. 建立连接 :
使用 DriverManager 类的 getConnection 方法,传入连接 URL、数据库用户名和密码,即可建立与数据库的实际网络连接。该方法会抛出 SQLException 异常,所以需要使用 try/catch 块进行异常处理。示例代码如下:
String username = "jay_debesee";
String password = "secret";
Connection connection = DriverManager.getConnection(oracleURL, username, password);
在建立连接后,还可以使用 Connection 类的 getMetaData 方法获取数据库的相关信息,如数据库名称、版本、JDBC 驱动名称和版本等。示例代码如下:
DatabaseMetaData dbMetaData = connection.getMetaData();
String productName = dbMetaData.getDatabaseProductName();
System.out.println("Database: " + productName);
String productVersion = dbMetaData.getDatabaseProductVersion();
System.out.println("Version: " + productVersion);
Connection 类还有其他一些有用的方法,如 prepareStatement (创建 PreparedStatement )、 prepareCall (创建 CallableStatement )、 rollback (回滚自上次提交以来的语句)、 commit (提交自上次提交以来的操作)、 close (关闭连接)和 isClosed (检查连接是否已超时或被显式关闭)等。
4. 创建 Statement 对象 :
Statement 对象用于向数据库发送 SQL 查询和命令。可以使用 Connection 对象的 createStatement 方法创建 Statement 对象。示例代码如下:
Statement statement = connection.createStatement();
- 执行查询 :
使用Statement对象的executeQuery方法可以执行 SQL 查询,并返回一个ResultSet对象,该对象包含查询结果。示例代码如下:
String query = "SELECT col1, col2, col3 FROM sometable";
ResultSet resultSet = statement.executeQuery(query);
如果要修改数据库,可以使用 executeUpdate 方法,并传入包含 UPDATE 、 INSERT 或 DELETE 语句的字符串。 Statement 类的其他有用方法还包括 execute (执行任意命令)和 setQueryTimeout (设置等待结果的最大延迟)等。此外,还可以创建参数化查询,将值提供给预编译的固定格式查询。
6. 处理结果 :
处理查询结果的最简单方法是逐行处理,使用 ResultSet 的 next 方法逐行遍历结果集。在每一行中,可以使用 ResultSet 提供的各种 getXxx 方法,根据列索引或列名获取不同 Java 类型的结果。例如,使用 getInt 获取整数值,使用 getString 获取字符串值等。需要注意的是,列索引从 1 开始,这遵循 SQL 约定,而不是像 Java 数组那样从 0 开始。示例代码如下:
while(resultSet.next()) {
System.out.println(resultSet.getString(1) + " " +
resultSet.getString(2) + " " +
resultSet.getString(3));
}
ResultSet 类除了 getXxx 和 next 方法外,还有其他有用的方法,如 findColumn (获取指定列名的索引)、 wasNull (检查上一次 getXxx 结果是否为 SQL NULL)和 getMetaData (获取 ResultSet 的元数据信息)等。 getMetaData 方法非常有用,它返回一个 ResultSetMetaData 对象,通过该对象可以动态获取结果集的列数、列名、列类型等信息。
7. 关闭连接 :
使用完数据库连接后,应该显式地关闭连接,以释放资源。可以使用 Connection 对象的 close 方法关闭连接。示例代码如下:
connection.close();
如果预计后续还会进行数据库操作,建议推迟关闭连接,因为打开连接的开销通常较大。实际上,重用现有连接是一种重要的优化策略。
下面是使用 JDBC 进行数据库操作的基本步骤流程图:
graph LR
A[加载 JDBC 驱动] --> B[定义连接 URL]
B --> C[建立连接]
C --> D[创建 Statement 对象]
D --> E[执行查询]
E --> F[处理结果]
F --> G[关闭连接]
2. 基本 JDBC 示例
为了更好地理解上述基本步骤,下面通过一个简单的示例来展示如何使用 JDBC 连接数据库并查询数据。示例中的 FruitTest 类可以连接到 Oracle 或 Sybase 数据库,并打印出 fruits 表中预定列的值。
FruitTest 类的代码如下:
package coreservlets;
import java.sql.*;
/** A JDBC example that connects to either an Oracle or
* a Sybase database and prints out the values of
* predetermined columns in the "fruits" table.
*/
public class FruitTest {
/** Reads the hostname, database name, username, password,
* and vendor identifier from the command line. It
* uses the vendor identifier to determine which
* driver to load and how to format the URL. The
* driver, URL, username, host, and password are then
* passed to the showFruitTable method.
*/
public static void main(String[] args) {
if (args.length < 5) {
printUsage();
return;
}
String vendorName = args[4];
int vendor = DriverUtilities.getVendor(vendorName);
if (vendor == DriverUtilities.UNKNOWN) {
printUsage();
return;
}
String driver = DriverUtilities.getDriver(vendor);
String host = args[0];
String dbName = args[1];
String url = DriverUtilities.makeURL(host, dbName, vendor);
String username = args[2];
String password = args[3];
showFruitTable(driver, url, username, password);
}
/** Get the table and print all the values. */
public static void showFruitTable(String driver,
String url,
String username,
String password) {
try {
// Load database driver if not already loaded.
Class.forName(driver);
// Establish network connection to database.
Connection connection =
DriverManager.getConnection(url, username, password);
// Look up info about the database as a whole.
DatabaseMetaData dbMetaData = connection.getMetaData();
String productName =
dbMetaData.getDatabaseProductName();
System.out.println("Database: " + productName);
String productVersion =
dbMetaData.getDatabaseProductVersion();
System.out.println("Version: " + productVersion + "\n");
System.out.println("Comparing Apples and Oranges\n" +
"============================");
Statement statement = connection.createStatement();
String query = "SELECT * FROM fruits";
// Send query to database and store results.
ResultSet resultSet = statement.executeQuery(query);
// Look up information about a particular table.
ResultSetMetaData resultsMetaData =
resultSet.getMetaData();
int columnCount = resultsMetaData.getColumnCount();
// Column index starts at 1 (a la SQL) not 0 (a la Java).
for(int i=1; i<columnCount+1; i++) {
System.out.print(resultsMetaData.getColumnName(i) +
" ");
}
System.out.println();
// Print results.
while(resultSet.next()) {
// Quarter
System.out.print(" " + resultSet.getInt(1));
// Number of Apples
System.out.print(" " + resultSet.getInt(2));
// Apple Sales
System.out.print(" $" + resultSet.getFloat(3));
// Number of Oranges
System.out.print(" " + resultSet.getInt(4));
// Orange Sales
System.out.print(" $" + resultSet.getFloat(5));
// Top Salesman
System.out.println(" " + resultSet.getString(6));
}
} catch(ClassNotFoundException cnfe) {
System.err.println("Error loading driver: " + cnfe);
} catch(SQLException sqle) {
System.err.println("Error connecting: " + sqle);
}
}
private static void printUsage() {
System.out.println("Usage: FruitTest host dbName " +
"username password oracle|sybase.");
}
}
为了方便管理驱动和生成连接 URL,示例中使用了 DriverUtilities 类,该类的代码如下:
package coreservlets;
/** Some simple utilities for building Oracle and Sybase
* JDBC connections. This is <I>not</I> general-purpose
* code -- it is specific to my local setup.
*/
public class DriverUtilities {
public static final int ORACLE = 1;
public static final int SYBASE = 2;
public static final int UNKNOWN = -1;
/** Build a URL in the format needed by the
* Oracle and Sybase drivers I am using.
*/
public static String makeURL(String host, String dbName,
int vendor) {
if (vendor == ORACLE) {
return("jdbc:oracle:thin:@" + host + ":1521:" + dbName);
} else if (vendor == SYBASE) {
return("jdbc:sybase:Tds:" + host + ":1521" +
"?SERVICENAME=" + dbName);
} else {
return(null);
}
}
/** Get the fully qualified name of a driver. */
public static String getDriver(int vendor) {
if (vendor == ORACLE) {
return("oracle.jdbc.driver.OracleDriver");
} else if (vendor == SYBASE) {
return("com.sybase.jdbc.SybDriver");
} else {
return(null);
}
}
/** Map name to int value. */
public static int getVendor(String vendorName) {
if (vendorName.equalsIgnoreCase("oracle")) {
return(ORACLE);
} else if (vendorName.equalsIgnoreCase("sybase")) {
return(SYBASE);
} else {
return(UNKNOWN);
}
}
}
运行 FruitTest 类时,需要传入主机名、数据库名、用户名、密码和数据库供应商标识符作为命令行参数。例如,连接到 Oracle 数据库的命令如下:
java coreservlets.FruitTest dbhost1.apl.jhu.edu PTE hall xxxx oracle
连接到 Sybase 数据库的命令如下:
java coreservlets.FruitTest dbhost2.apl.jhu.edu 605741 hall xxxx sybase
运行上述命令后,程序会输出数据库的名称、版本以及 fruits 表的查询结果。
以下是 FruitTest 类的执行流程表格:
| 步骤 | 操作 | 代码示例 |
| — | — | — |
| 1 | 检查命令行参数 | if (args.length < 5) { printUsage(); return; } |
| 2 | 获取数据库供应商标识符 | int vendor = DriverUtilities.getVendor(vendorName); |
| 3 | 获取驱动名称和连接 URL | String driver = DriverUtilities.getDriver(vendor); String url = DriverUtilities.makeURL(host, dbName, vendor); |
| 4 | 调用 showFruitTable 方法 | showFruitTable(driver, url, username, password); |
| 5 | 加载驱动 | Class.forName(driver); |
| 6 | 建立连接 | Connection connection = DriverManager.getConnection(url, username, password); |
| 7 | 获取数据库元数据 | DatabaseMetaData dbMetaData = connection.getMetaData(); |
| 8 | 创建 Statement 对象 | Statement statement = connection.createStatement(); |
| 9 | 执行查询 | ResultSet resultSet = statement.executeQuery(query); |
| 10 | 获取结果集元数据 | ResultSetMetaData resultsMetaData = resultSet.getMetaData(); |
| 11 | 打印列名 | for(int i=1; i<columnCount+1; i++) { System.out.print(resultsMetaData.getColumnName(i) + " "); } |
| 12 | 打印查询结果 | while(resultSet.next()) { ... } |
| 13 | 异常处理 | catch(ClassNotFoundException cnfe) { ... } catch(SQLException sqle) { ... } |
3. 一些 JDBC 实用工具
在许多应用程序中,并不需要逐行处理查询结果。例如,在 Servlet 和 JSP 页面中,通常会将数据库结果(将所有值视为字符串)进行格式化,并以 HTML 表格(见相关部分)、Excel 电子表格(见相关部分)的形式呈现给用户,或者将结果分散在页面中展示。在这种情况下,拥有能够检索并存储整个 ResultSet 以便后续显示的方法可以简化处理过程。
本节介绍两个类,它们提供了这种基本功能以及一些格式化、显示和表创建实用工具。核心类是 DatabaseUtilities ,它实现了四个常见任务的静态方法:
-
getQueryResults :
此方法连接到数据库,执行查询,将所有行作为字符串数组检索出来,并将它们放入DBResults对象中(见相关代码)。该方法还会将数据库产品名称、数据库版本、所有列的名称以及Connection对象放入DBResults对象中。getQueryResults有两个版本:一个用于建立新连接,另一个用于使用现有连接。 -
createTable :
给定表名、表示列格式的字符串以及表示行值的字符串数组,此方法连接到数据库,删除指定表的任何现有版本,使用指定格式发出CREATE TABLE命令,然后为每一行发送一系列INSERT INTO命令。同样,有两个版本:一个用于建立新连接,另一个用于使用现有连接。 -
printTable :
给定表名,此方法连接到指定的数据库,检索所有行,并将它们打印到标准输出。它通过将表名转换为SELECT * FROM tableName形式的查询,并将其传递给getQueryResults来检索结果。
下面是使用这些实用工具创建 fruits 表的示例代码 FruitCreation 类:
package coreservlets;
import java.sql.*;
/** Creates a simple table named "fruits" in either
* an Oracle or a Sybase database.
*/
public class FruitCreation {
public static void main(String[] args) {
if (args.length < 5) {
printUsage();
return;
}
String vendorName = args[4];
int vendor = DriverUtilities.getVendor(vendorName);
if (vendor == DriverUtilities.UNKNOWN) {
printUsage();
return;
}
String driver = DriverUtilities.getDriver(vendor);
String host = args[0];
String dbName = args[1];
String url =
DriverUtilities.makeURL(host, dbName, vendor);
String username = args[2];
String password = args[3];
String format =
"(quarter int, " +
"apples int, applesales float, " +
"oranges int, orangesales float, " +
"topseller varchar(16))";
String[] rows =
{ "(1, 32248, 3547.28, 18459, 3138.03, ’Maria’)",
"(2, 35009, 3850.99, 18722, 3182.74, ’Bob’)",
"(3, 39393, 4333.23, 18999, 3229.83, ’Joe’)",
"(4, 42001, 4620.11, 19333, 3286.61, ’Maria’)" };
Connection connection =
DatabaseUtilities.createTable(driver, url,
username, password,
"fruits", format, rows,
false);
// Test to verify table was created properly. Reuse
// old connection for efficiency.
DatabaseUtilities.printTable(connection, "fruits",
11, true);
}
private static void printUsage() {
System.out.println("Usage: FruitCreation host dbName " +
"username password oracle|sybase.");
}
}
运行 FruitCreation 类时,同样需要传入主机名、数据库名、用户名、密码和数据库供应商标识符作为命令行参数。例如:
java coreservlets.FruitCreation dbhost1.apl.jhu.edu PTE hall xxxx oracle
以下是 FruitCreation 类的执行流程表格:
| 步骤 | 操作 | 代码示例 |
| — | — | — |
| 1 | 检查命令行参数 | if (args.length < 5) { printUsage(); return; } |
| 2 | 获取数据库供应商标识符 | int vendor = DriverUtilities.getVendor(vendorName); |
| 3 | 获取驱动名称和连接 URL | String driver = DriverUtilities.getDriver(vendor); String url = DriverUtilities.makeURL(host, dbName, vendor); |
| 4 | 调用 createTable 方法创建表 | Connection connection = DatabaseUtilities.createTable(driver, url, username, password, "fruits", format, rows, false); |
| 5 | 调用 printTable 方法验证表是否创建成功 | DatabaseUtilities.printTable(connection, "fruits", 11, true); |
下面是使用这些 JDBC 实用工具的整体流程图:
graph LR
A[开始] --> B[检查参数]
B --> C{参数是否足够}
C -- 是 --> D[获取供应商信息]
C -- 否 --> E[打印使用说明并退出]
D --> F[获取驱动和 URL]
F --> G{选择操作}
G -- 创建表 --> H[调用 createTable]
G -- 查询结果 --> I[调用 getQueryResults]
G -- 打印表 --> J[调用 printTable]
H --> K[验证表创建]
I --> L[处理结果]
J --> M[输出结果]
K --> N[结束]
L --> N
M --> N
总结
通过上述内容,我们详细介绍了使用 JDBC 进行数据库操作的基本步骤,包括加载驱动、定义连接 URL、建立连接、创建 Statement 对象、执行查询、处理结果和关闭连接等。同时,通过 FruitTest 示例展示了如何使用这些步骤连接到不同的数据库并查询数据,以及使用 DriverUtilities 类来管理驱动和生成连接 URL。此外,还介绍了一些 JDBC 实用工具,如 DatabaseUtilities 类提供的 getQueryResults 、 createTable 和 printTable 方法,这些工具可以简化数据库操作的处理过程。
在实际应用中,我们可以根据具体需求选择合适的方法和工具,同时要注意异常处理和资源管理,以确保程序的稳定性和性能。例如,在使用完数据库连接后,要及时关闭连接,避免资源泄漏;在处理查询结果时,可以根据需要选择逐行处理或使用实用工具一次性处理整个结果集。
希望这些内容能够帮助你更好地理解和使用 JDBC 进行数据库操作。如果你有任何疑问或需要进一步的帮助,请随时留言。
超级会员免费看
1158

被折叠的 条评论
为什么被折叠?



