通过JDBC访问数据库
JDBC是什么?
如果您已经学习了 “使用 JDBC将 XML 数据插入数据库”教程,那么可以直接跳到 SELECT语句剖析 一节。
就在不久之前,要与数据库交互,开发人员必须使用针对该数据库的特定 API。这使得创建独立于数据库的应用程序非常困难,甚至完全不可能。
JDBC 类似于 ODBC(即开放数据库连接),提供了访问数据库的标准 API 中介。从左侧的资料中可以了解到,可以使用标准 JDBC命令,JDBC驱动程序会将其转为针对数据库的原生 API。
本教程的任何内容均未提及特定数据库,因为选择哪种数据库是无关紧要的。所有命令均为标准 JDBC命令,驱动程序可将其转为适合您选择的任意数据库的原生命令。由于这种 API独立性,因此您在一定程度上可以轻松使用另外一种数据库,除了驱动程序名称和可能需要更改的连接 URL(在 创建连接 时使用)之外,您不需要更改应用程序中的任何内容。
有关为您的数据库下载恰当的 JDBC驱动程序的信息,请参阅 参考资料 部分。可用的JDBC驱动程序超过 150种,实际上适合任何数据库。
甚至还有适用于不具备可用 JDBC驱动程序的数据库的选项。
图 1.无 JDBC 驱动程序的数据库的示例
JBDC-ODBC 桥接
只要有ODBC驱动程序可用,那么针对某种数据库的特定 JDBC驱动程序就并非必不可少;您可以使用 JDBC-ODBC 桥接 取而代之。应用程序将调用桥接,桥接将命令转为 ODBC,ODBC驱动程序将其转为原生 API。
出于多种原因,并不推荐使用 JDBC-ODBC桥接来访问数据库,其中包括性能和配置方面的原因(命令必须通过两个 API传递,必须在每一个客户端上安装和配置 ODBC驱动程序),但是,如果无纯粹的 JDBC驱动程序可用,那么使用桥接来进行测试和开发也是一种可以接受的做法。
如果您选择使用桥接,那么在 Windows系统中应该选择 Start>Settings>Control Panel>ODBCData Sources 来创建一个系统数据源名称 (DSN)。记下 DSN的名称,在 创建连接 时需要使用此名称。
图 2.具有 JDBC 和驱动程序的数据库的示例
create table products ( product_id numeric primary key, product_name varchar(50), base_price numeric, size numeric, unit varchar(10), lower numeric, upper numeric, unit_price numeric ) |
首先,请确保已安装了您选择使用的所有数据库,并且它们都能正常运行,此外还要确保驱动程序是可用的。可以从http://industry.java.sun.com/products/jdbc/drivers 下载JDBC驱动程序。
创建数据库之后,再创建必要的表。本教程仅使用一个表,即 products。其结构如左侧所示。通过采用适合您的数据库的恰当步骤来创建表。
注意:在一般情况下,此数据应至少会拆分到两个相关的表中;为了简便起见,本示例仅使用了一个表。
使用Java与数据库交互通常涉及以下步骤:
- 载入数据库驱动程序。这可以是 JDBC驱动程序,也可以是 JDBC-ODBC桥接。
- 为数据库创建一个 Connection。
- 创建一个 Statement 对象。此对象实际上会执行 SQL或存储过程。
- 创建一个 ResultSet,并使用所执行的查询的结果填充它(如果目标是检索数据或直接更新数据)。
- 检索或更新 ResultSet 中的数据。
java.sql 包中包含 JDBC 2.0 Core API,它是JavaTM 2 SDK, Standard Edition 发行版本的一部分,用于访问数据库。javax.sql 包是作为 Java 2 SDK, Enterprise Edition 的一部分发布的,其中包含 JDBC 2.0 Optional Package API。
本教程仅使用JDBC 2.0 Core API中的类。
为了访问数据库,首先要加载 JDBC驱动程序。在任意给定时间,如果有多种驱动程序可用,DriverManager 会尝试创建与它所知道的每一种驱动程序之间的连接,从而确定需要使用哪种驱动程序。应用程序将使用成功连接的第一个驱动程序。DriverManager 可以通过两种方式得知驱动程序的存在。
第一种方式是直接使用 Class.forName() 加载,如本例中所示。载入驱动程序类之后,它将向 DriverManager 进行注册,如下所示:
public class Pricing extends Object {
public static void main (String args[]){
//For the JDBC-ODBC bridge, use //driverName = "sun.jdbc.odbc.JdbcOdbcDriver" String driverName = "JData2_0.sql.$Driver";
try { Class.forName(driverName); } catch (ClassNotFoundException e) { System.out.println("Error creating class: "+e.getMessage()); } } } |
获得一个成功加载的驱动程序之后,应用程序即可连接到数据库。
DriverManager 可用于定位一个驱动程序的第二种方法就是循环获取 sql.drivers 系统属性中找到的任何驱动程序。sql.drivers 属性是可能存在的驱动程序的冒号分隔列表。在加载类之前,将始终动态检查此列表,因此如果您希望使用某种特殊驱动程序,请确保sql.drivers 属性为空,或者从您需要的驱动程序开始。
加载驱动程序之后,应用程序即可连接到数据库。
DriverManager 将通过静态 getConnection() 方法建立连接,该方法将获取数据库的 URL 作为参数。URL通常表示为:
jdbc:<sub-protocol>:databasename |
然而,引用URL可以使用活动驱动程序能够理解的任何格式编写。请查询您的 JDBC驱动程序的文档,以便确定 URL格式。
一种需要使用子协议的场景就是通过 ODBC进行连接。如果直接通过 ODBC访问 DSN为 pricing 的示例数据库,那么 URL 应该是:
odbc:pricing |
这就意味着,要通过JDBC进行连接,URL将是:
jdbc:odbc:pricing |
实际连接创建如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;
public class Pricing extends Object {
public static void main (String args[]){
//For the JDBC-ODBC bridge, use //driverName = "sun.jdbc.odbc.JdbcOdbcDriver" //and //connectURL = "jdbc:odbc:pricing" String driverName = "JData2_0.sql.$Driver"; String connectURL = "jdbc:JDataConnect://127.0.0.1/pricing"; Connection db = null; try { Class.forName(driverName); db = DriverManager.getConnection(connectURL); } catch (ClassNotFoundException e) { System.out.println("Error creating class: "+e.getMessage()); } catch (SQLException e) { System.out.println("Error creating connection: "+e.getMessage()); } } } |
成功创建连接后,即可执行任何所需的数据库操作(例如,插入或更新数据)。
由于 Statement 和 Connection 是对象,因此 Java 将对其执行垃圾收集,释放它们占用的数据库资源。这可能会误导您认为这代表您无需为关闭这些对象而担忧,但实际上并非如此。
Java 应用程序本身完全有可能拥有大量可用资源,也就是说垃圾收集的频率较低。此外,在 Java应用程序拥有大量资源时,可用的数据库资源可能受到限制。Java对象也许会占用大量数据库资源,而这些对象很有可能被应用程序关闭。
无论是否存在错误,都有必要确保这些对象已关闭,因此应该为已有的 try-catch 块添加一个 finally 块。
... Connection db = null; try { Class.forName(driverName); db = DriverManager.getConnection(connectURL); } catch (ClassNotFoundException e) { System.out.println("Error creating class: "+e.getMessage()); } catch (SQLException e) { System.out.println("Error creating connection: "+e.getMessage()); } finally { System.out.println("Closing connections..."); try { db.close(); } catch (SQLException e) { System.out.println("Can't close connection."); } } } } |
具有讽刺意味的是,close() 方法本身可能会引发一个 SQLException,因此需要自己的 try-catch 块。
本文来自:http://www.ibm.com/developerworks/cn/xml/tutorials/x-extract/section2.html