首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java
2.2  JDBC技术基础

大量的数据库厂商和第三方开发商支持Java的JDBC标准,并开发了各种针对不同数据库的JDBC驱动程序,这些驱动程序分为四类,我们将逐一进行介绍。

2.2.1  JDBC-ODBC桥

在微软公司的大力推广下,ODBC作为一种数据库接口标准,已经被大家广泛使用,因此在Java访问数据库的解决方案中,最直接的做法就是建立Java和ODBC之间的关联,这样就可以轻松地在Java中访问各种ODBC所支持的数据库系统了。

JDBC-ODBC桥与ODBC驱动程序提供了一种把JDBC调用映射到ODBC调用的方法。和所有通过ODBC访问数据库的系统一样,JDBC-ODBC桥客户端必须安装ODBC驱动程序作为一组本机库。由于ODBC是流行的DBMS接口标准,已经有许多可用的ODBC驱动程序与大量数据库交互,Sun提供桥接驱动的目的是用于传统的数据库应用系统。如图2-1所示是JDBC-ODBC桥的体系结构。

 

图2-1  JDBC/ODBC桥的体系结构

这种驱动程序会在客户端装载二进制代码,而且它并不支持完整的JAVA命令集;另一个重要的原因是由于JDBC-ODBC桥的连接方式需要将Java访问数据库的请求转化为ODBC的指令;从数据库返回的结果集也需要先转化为ODBC的格式,再转为Java所支持的数据格式,如此频繁的转化使得JDBC-ODBC桥连接方式的执行效率相对较低。

因此Sun并不鼓励将这种连接方式运用在大型系统开发中。

2.2.2  本地API半Java驱动程序

本地API半Java驱动程序是一部分API用Java来编写的驱动程序。这种类型的驱动程序把客户机上的JDBC调用转换为Oracle、Sybase、DB2等主流数据库API的本机调用。这种类型的驱动程序和JDBC-ODBC桥驱动程序一样,要求将某些二进制代码加载到每台客户机上。此外,这种类型的驱动程序要求针对特定的平台开发,因此对于真正使用JAVA开发的系统并不建议使用这种驱动程序,因为它将破坏JAVA垮平台的特性。图2-2给出了这种驱动程序的体系结构。

 

图2-2  本地API半Java驱动程序的体系结构

2.2.3  JDBC-NET纯Java驱动程序

第三类驱动程序是面向数据库中间件的纯JAVA驱动程序。JDBC调用被转换为与DBMS无关的网络协议,然后,某个服务器再将这种协议转换为一种DBMS协议。网络服务器中间件能够将它的纯Java客户机连接到多种不同的数据库上。这种驱动程序以服务器为基础,不再需要客户端本机的代码,这使得它运行起来要比前两类驱动程序快。此外,开发者可以用一个驱动程序连接不同的数据库,可以说,这是最为灵活的JDBC驱动程序。图2-3是JDBC-NET纯Java驱动程序的体系结构图。

 

图2-3  JDBC-NET纯Java驱动程序

2.2.4  本地协议纯Java驱动程序

这种类型的驱动程序直接面向数据库,它将JDBC调用转换为可直接被DBMS使用的网络协议。这样,客户端可以直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。但是,这些协议都是专用的,不同的数据库有不同的驱动程序,因此,在异构系统中可能会有驱动程序比较多的问题。不过这种类型的驱动程序有较高的性能,可以直接访问数据库,那么这个问题也就不那么严重了。其体系结构如图2-4所示。

通过上面的介绍可以看出,对于Java开发者来说,第三类和第四类纯Java的驱动程序都是不错的选择,它们在性能和可移植性上都好于另外两类驱动程序。

 

图2-4  本地协议纯Java驱动程序

2.2.5  JDBC常用类简介

JDBC是由java.sql包实现的,下面我们介绍其中主要几个接口(类),包括:

—   DriverManger

—   Connection

—   Statement

—   PrepareStatement

—   ResultSet

DriverManager类

DriverManager类是JDBC的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。DriverManager类的常用方法介绍如下。

â registerDriver(Driver driver)

DriverManage通过调用方法registerDriver注册JDBC驱动程序。而JDBC-ODBC是在JDK中自带的,所以不需要再注册,只需要装载即可。通过调用方法Class.forName将显式地加载驱动程序类。下面是装载JDBC-ODBC桥驱动程序的代码:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

其他的JDBC则需要先装载再注册。下列代码装载并注册SQLServer驱动程序:

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

Java.sql.DriverManager.registerDriver(

new com.microsoft.jdbc.sqlserver.SQLServerDriver)

有些驱动程序是不需要用户直接调用DriverManager.registerDriver方法来注册的,因为驱动程序会在加载时自动创建实例并调用DriverManager.registerDriver方法注册自身,此时用户只要加载驱动程序就可以了。

â getConnection(String url,String user,String pwd)

对于简单的应用程序,一般程序员需要在此类中直接使用的唯一方法是DriverManager.getConnection。正如名称所示,该方法将建立与数据库的连接。

在加载并注册了驱动程序后应该调用此方法来获得数据库连接。该方法有三个参数,url表示连接数据库的JDBC URL,user和pwd分别表示连接数据库的用户名和密码。

一个JDBC URL由三部分组成:(1)协议标识(总是jdbc);(2)驱动程序名或数据库连接机制(如odbc、sqlserver、oracle等);(3)数据库标识(不同的驱动程序其格式不同)。例如,使用JDBC-ODBC桥驱动程序时,url可以写成如下形式:

jdbc:odbc:workflow

其中,“odbc”是驱动程序名;“workflow”就是数据库标识,这里是数据库名。

如果是使用Oracle的JDBC驱动程序,则URL应该写成如下形式:

jdbc:oracle:thin:@192.168.1.88:1521:orcl

其中,“oracle:thin”是驱动程序名;“@localhost:1521:orcl”是数据库标识;“localhost”是数据库服务器的标识,通常是IP地址;“1521”是oracle数据库的端口号;“orcl”是数据库的SID。

â setLoginTimeout(int seconds)

该类用于设定数据库连接时等待的最长时间(以秒为单位)。

Connection类

Connection类代表与数据库的连接。一个应用程序可与单个数据库有一个或多个连接,或者可与多个数据库有连接。Connection类的常用方法有以下两个。

—   createStatement():用来创建Statement对象。

—   PrepareStatement(String sql):用来创建PreparedStatement对象。参数“sql”是带有一个或多个参数的SQL语句。

Statement类

Statement对象用于执行不带参数的静态SQL语句。Statement接口提供了执行语句和获取结果的基本方法。

(1)创建Statement对象:

建立数据库的连接之后,Connection对象调用createStatement创建Statement对象,如:

Connection con = DriverManager.getConnection(url, "sunny", "ss");

Statement stmt = con.createStatement();

(2)使用Statement对象执行语句:

Statement接口提供了三种执行SQL语句的方法:executeQuery、executeUpdate和execute。使用哪一种方法由SQL语句所产生的内容决定。下面具体介绍一下这三种方法。

â executeQuery

最常用的方法之一,用于向数据库系统发送检索指令,并从数据库中获得查询到的结果集的方法。如果发送一个SELECT语句,该方法返回一个ResultSet对象,例如:

String sql ="SELECT a, b, c FROM Table2";

ResultSet rs = stmt.executeQuery(sql);

â executeUpdate

用于执行INSERT、UPDATE或DELETE语句以及SQL DDL(数据定义语言)语句。executeUpdate的返回值是一个整数,指示受影响的行数。

â execute

用于执行返回多个结果集、多个更新计数或二者组合的语句。

(3)关闭Statement对象:

Statement对象将由Java垃圾收集程序自动关闭。而作为一种好的编程风格,应在不需要Statement对象时显式地关闭它们。这将立即释放DBMS资源,有助于避免潜在的内存溢出问题。

PreparedStatement类

PreparedStatement接口由Statement继承而来,用于动态执行带参数的SQL语句。在很多情况下,我们可能会多次执行同样的一条SQL语句,但是每次执行时所需要的参数又不一样,例如:

Select bookname from book where auther = ‘zhangsan’;

Select bookname from book where auther = ‘lisi’;

Select bookname from book where auther = ‘sunny’;

对于这样的三条语句,如果使用Statement对象,则需要创建三个Statement对象,而使用PreparedStatement对象,只需要创建一次就可以了,这时,SQL语句的格式如下所示:

         Select bookname from book where auther =?;

作为Statement的子类,PreparedStatement继承了Statement的所有功能。另外它还添加了一整套方法,用于设置SQL语句中代表参数“?”的值。

使用PreparedStatement的步骤可以归结为如下几步。

(1)创建PreparedStatement对象:

以下的代码段创建了包含两个参数的SQL语句的PreparedStatement对象。

Connection con = DriverManager.getConnection(url, "sunny", "ss");

String sql="UPDATE table4 SET m = ? WHERE x = ?"

PreparedStatement pstmt = con.prepareStatement(sql);

(2)设置参数的值:

在执行PreparedStatement对象之前,必须设置每个“?”参数的值。这可以通过调用set×××方法来完成,其中×××是与该参数相应的类型。set×××方法的第一个参数是要设置参数的序数位置,第二个参数是赋给该参数的值。例如:

pstmt.setLong(1,123456789);//设置第一个参数的值为123456789

pstmt.setString(2," Good");//设置第二个参数的值为"Good"

ResultSet类

ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next()方法用于移动到ResultSet中的下一行,使下一行成为当前行。

下面的代码段是执行SQL语句的示例。该SQL语句将返回行集合,其中列1为int,列2为String,而列3则为float。

java.sql.Statement stmt = conn.createStatement();

ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");

While (r.next())

{

    // 向屏幕输出当前记录的各个字段的值

    int i = r.getInt("a");

    String s = r.getString("b");

    float f = r.getFloat("c");

    System.out.println("ROW = " + I + " " + s + " " + f);

}

â next()

ResultSet维护指向其当前数据行的光标。每调用一次next()方法,光标向下移动一行。最初它位于第一行之前,因此第一次调用next()将把光标置于第一行上,使它成为当前行。每次调用next()导致光标向下移动一行,按照从上至下的次序获取ResultSet行。

在ResultSet对象或其父辈Statement对象关闭之前,光标一直保持有效。

â get×××()

get×××方法提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。

列名或列号可用于标识要从中获取数据的列。例如,如果ResultSet对象rs的第二列名为“title”,并将值存储为字符串,则下列任一代码都将获取存储在该列中的值:

String s = rs.getString("title");

String s = rs.getString(2);

用户不必关闭ResultSet;当产生它的Statement关闭、重新执行或用于从多个结果序列中获取下一个结果时,该ResultSet将被Statement自动关闭。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论