
2.3 JDBC简介
Web应用程序常常需要和数据库交互,将数据保存到数据库,从数据库取出数据等。Web应用程序对数据库的操作主要是4种:插入记录、删除记录、更新记录、查询符合条件的记录,这4种操作常称为CRUD。现在的数据库主要是关系数据库。常见的关系数据库有Oracle、DB2、Microsoft SQL Server、MySQL等。Java应用程序要连接数据库就需要JDBC技术。
在介绍JDBC前先介绍在SQL常用的语句,详细的SQL语句和数据库操作请参见相应的数据库书籍。
2.3.1 常用的标准SQL语句
(1)创建数据库语句如下:
Create database databaseName
上述语句会创建一个名字叫databaseName的数据库。
(2)删除数据库语句如下:
Drop database databaseName
上述语句将删除databaseName数据库。
(3)创建表的语句格式如下:
Create table tableName (column1 datatype[column_constraint], column1 datatype[column_constraint], … [Constrain primary key pk_table_name(column_n)]
以SQLServer数据库为例,用SQL语句创建用户表user,该表有id、name、password、email、age、birthday、money字段,数据库中字段的数据类型分别是int、varchar、varchar、varchar、int、datetime、float型。由于在数据库SQL Server中user是关键字,不允许用户直接使用,因此在user的两边加上[]。
create table [user](id int, name varchar(50), password varchar(50), email varchar(50), age int, birthday datetime);
(4)删除表的语句如下:
drop table tableName;
例如,以下语句用于删除表user。
drop table [user];
(5)插入一条记录的语句格式如下:
insert into tableName(column1,column2,……) values(value1,value2,……);
例如,向user表中插入一条记录。
insert into [user](name,password,email,age,birthday) values('Funson','888','Funson@163.com',28,'1988-12-08',66.0);
(6)删除符合条件的一条或多条记录:
delete from tableName [where …];
例如,删除user表中id是1的记录。
delete from user where id=1;
如果去掉where子句,将删除user表中所有的记录。
(7)更新一条或多条记录:
update tableName set columnName=newColumnValue;
例如,以下语句更新user表中id=1的password字段,字段原来的值是123,更新后为456。
update [user] set password='456';
以上简要介绍了常用的SQL语句,为了能在Java程序中操作数据库,还需要使用JDBC。
2.3.2 JDBC结构
JDBC的全称是Java Database Connectivity,是一个应用程序编成接口(API),包括了许多类和接口,程序员通过使用JDBC可以方便地将SQL语句传送给几乎任何一种数据库。
简单地说,JDBC主要完成3件事:
与一个数据库建立连接;向数据库发送SQL语句;处理数据库返回的结果。具体操作步骤如下。
(1)向驱动程序管理器加载注册JDBC驱动程序。
(2)获得特定数据库的连接。
(3)得到SQL语句容器,并发送SQL语句。
(4)如果有结果集返回的话,处理结果集。
(5)关闭数据库连接。
Sun公司的JDBC规范定义了如何操作数据库的一组标准,数据库厂商要实现这些标准来完成真正的数据库操作。这有些像在Java语言中的接口和实现类,Sun公司的标准类似接口,数据库厂商的实现类似实现类。接口只是定义如何做某件事,但是不能真正做;实现类能真正能完成接口中定义的操作。
JDBC的体系结构,如图2-1所示,其包含4个组件:

图2-1 JDBC体系结构
(1)Java应用程序。Java应用程序负责用户与用户接口之间的JDBC交互操作,以及调用JDBC的对象方法以给出SQL语句并提取结果。
(2)JDBC驱动程序管理器。JDBC驱动程序管理器为应用程序加载和调用驱动程序。
(3)JDBC驱动程序。JDBC驱动程序执行JDBC对象方法的调用,发送SQL请求给指定的数据源,并将结果返回给应用程序。驱动程序也负责与任何访问数据源的必要软件层进行交互。
(4)数据源。数据源由数据集和与其相关联的环境组成,主要指各数据库厂商的数据库系统。
在Java应用程序中使用JDBC的API来访问数据库时,需要在系统环境变量CLASSPATH中加载某个具体的数据库的JDBC驱动,这样不管是什么数据库,只要有驱动,在Java程序中使用统一的类和接口就能完成对数据库的操作了。如图2-2所示为Java SQL驱动核心类与接口。

图2-2 JDBC驱动核心类与接口
总体而言,JDBC包含以下几大角色:Driver、DriverManager、Connection、Statement、ResultSet。
❑ 数据库驱动Driver:JDBC的驱动程序,通过指定的URL创建数据库连接。
❑ 驱动程序管理器DriverManager:DriverManager可以注册和删除加载的驱动程序,可以根据给定的URL获取符合URL协议的驱动Driver或者是建立Connection连接,进行数据库交互。获取连接对象Connection DriverManager.getConnection(连接字符串,用户名,密码),注册驱动程序DriverManager.registerDriver(new oracle.jdbc.driver. OracleDriver())。
❑ 连接对象Connection:Driver或者DriverManager根据连接的URL和参数信息创建Connection实例,用来维持和数据库的数据通信,如果没有销毁或者调用close()对象,此对象和数据库的对象会一直保持连接。
❑ 命令对象Statement:Connection创建Statement对象,表示需要执行的SQL语句或者存储过程。
❑ 结果对象ResultSet:表示Statement执行完SQL语句后返回的结果集。
2.3.3 JDBC驱动类型
JDBC数据库驱动程序Driver的4种类型如下。
❑ 类型1:JDBC-ODBC桥接器。
❑ 类型2:本机API Java驱动程序。
❑ 类型3:JDBC网络纯Java驱动程序。
❑ 类型4:本地协议纯Java驱动。
第一种驱动类型JDBC-ODBC桥接器:因为微软推出的ODBC比JDBC出现的较早,所以绝大多数的数据库都可以通过ODBC来访问,当Sun公司推出JDBC的时候,为了支持更多的数据库,提供了JDBC-ODBC桥。这样开发者就可以使用JDBC的API通过ODBC去访问数据库。可以看到通过JDBC-ODBC桥访问数据库需要经过多层调用,因此效率较低。但是在数据库没有提供JDBC驱动只提供ODBC驱动的情况下,只能通过这种方式访问数据库。例如,Java若要访问Microsoft Access数据库,则只能通过这种方法访问。其驱动程序为sun.jdbc.odbc.JdbcOdbcDriver,如图2-3所示。

图2-3 JDBC-ODBC桥接器
该方式缺点:增加了ODBC层后导致效率低。JDBC-ODBC桥不支持分布式(除非ODBC驱动本身支持分布式)。
第二种驱动类型本机API Java驱动程序:部分Java驱动程序直接将JDBC API翻译成具体数据库的API。效率比第一种驱动高,缺点是客户端需要安装具体数据库的驱动。用这种方式访问数据库需要在客户机上安装本地JDBC驱动和特定数据库厂商的本地API,如图2-4所示。

图2-4 本机API Java驱动程序
第三种驱动类型JDBC网络纯Java驱动程序:纯Java驱动程序将JDBC API转换成独立于数据库的协议。网络协议Java驱动程序是最好的驱动程序,因为它通常提供了最佳的性能,并允许开发者利用特定数据库的功能,如图2-5所示。

图2-5 JDBC网络纯Java驱动程序
Java应用程序通过JDBC网络纯Java驱动程序,将JDBC调用发送给应用程序服务器,应用程序服务器与数据库完成通信,从而完成请求。
第四种驱动类型本地协议纯Java驱动:Java应用程序通过纯Java驱动程序与支持JDBC的数据库直接通信。这种方式是效率最高的访问方式。访问不同厂商的数据库,需要不同的JDBC驱动程序。目前,几个主要的数据厂商(Oracle、Microsoft SQL Server、Sybase等)都提供了对JDBC的支持,如图2-6所示。

图2-6 本地协议纯Java驱动
2.3.4 常用数据库JDBC连接写法
在需要通过JDBC连接数据库系统时,需要以下两个步骤。
❑ 驱动程序类名:一个继承java.sql.Driver接口的类名,JDBC驱动程序管理器需要加载这个类来处理数据库驱动程序。
❑ 数据库URL:一个字符串,该字符串包含关于数据库连接的信息和其他配置属性。这个字符串有自己的格式,不同数据库之间存在不同的格式。
常见的JDBC数据库连接的驱动名称及URL如下。
(1)MySQL
驱动程序包:mysql-connector-java-5.1.18-bin.jar;
驱动程序类名:com.mysql.jdbc.Driver;
URL格式:jdbc:mysql://servername:port/database。
Class.forName( " com.mysql.jdbc.Driver " ); cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerName Or IP:3306/myDatabaseName", sUsr, sPwd );
(2)PostgreSQL
驱动程序包:pgjdbc2.jar;
驱动程序类名:org.postgresql.Driver;
URL格式:jdbc:postgresql:// servername / database。
Class.forName( "org.postgresql.Driver" ); cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
(3)Oracle
驱动程序包:ojdbc6.jar;
驱动程序类名:oracle.jdbc.driver.OracleDriver;
URL格式:jdbc:oracle:thin:@<database>。
Class.forName( "oracle.jdbc.driver.OracleDriver" ); cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerName Or IP:1521:ORCL", sUsr, sPwd );
(4)Sybase
驱动程序包:jconn2.jar;
驱动程序类名:com.sybase.JDBC.SybDriver;
URL格式:JDBC:sybase:Tds: servername:5007/ database。
Class.forName( "com.sybase. JDBC.SybDriver" ); cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerName Or IP:5007/myDatabaseName ", sUsr, sPwd ); //(Default-Username/Password: "dba"/"sql")
(5)Microsoft SQLServer
驱动程序包:sqljdbc4.jar;
驱动程序类名:com.microsoft.JDBC.sqlserver.SQLServerDriver;
URL格式:JDBC:microsoft:sqlserver:// servername:1433;DatabaseName= master。
Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" ); cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerName Or IP:1433;databaseName=master", sUsr, sPwd );
(6)Informix
驱动程序包:ifxjdbc.jar;
驱动程序类名:com.informix.JDBC.ifxDriver;
URL格式:JDBC:informix-sqli:localhost:1533/database:INFORMIXSERVER=myserver。
Class.forName( " com.informix.JDBC.ifxDriver " ); Connection cn = DriverManager.getConnection( " JDBC:informix-sqli: localhost:1533/ database: INFORMIXSERVER=myserver"user=testUser;password=testpassword” );
2.3.5 创建JDBC应用程序具体步骤
通过前面的JDBC知识的学习,下面通过建立一个JDBC应用程序的具体实例进一步掌握其用法,一般有6个步骤。
(1)导入包
需要有软件包包含数据库编程所需的JDBC类。大多数情况下,使用import java.sql.*就足够了,代码如下:
//STEP 1. 导入所需包 import java.sql.*;
(2)注册JDBC驱动程序
这一步需要初始化驱动程序,这样就可以打开与数据库的通信信道。以下是代码片段实现这一目标:
//STEP 2: 注册JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); //连接MySQL数据库
(3)打开一个连接
这一步需要使用DriverManager.getConnection()方法创建一个Connection对象,它代表一个物理连接的数据库,代码如下:
//STEP 3: 打开一个连接 // Database credentials static final String USER = "username"; static final String PASS = "password"; System.out.println("Connecting to database…"); conn = DriverManager.getConnection(DB_URL,USER,PASS);
(4)执行一个查询
这一步需要使用一个对象类型Statement或PreparedStatement构建,并提交一个SQL语句到数据库。代码如下:
//STEP 4: 执行查询 System.out.println("Creating statement…"); stmt = conn.createStatement(); String sql; sql = "SELECT id, first, last, age FROM Employees"; ResultSet rs = stmt.executeQuery(sql);
如果有一个SQL UPDATE、INSERT或DELETE语句,那么需要下面的代码片段:
//STEP 4: 执行查询 System.out.println("Creating statement…"); stmt = conn.createStatement(); String sql; sql = "DELETE FROM Employees"; ResultSet rs = stmt.executeUpdate(sql);
(5)从结果集中提取数据
这一步是必需的情况下,从数据库中获取数据。可以使用适当的ResultSet.getXXX()方法来检索数据结果
//STEP 5: 从结果集中提取数据 while(rs.next()){ //Retrieve by column name int id = rs.getInt("id"); int age = rs.getInt("age"); String first = rs.getString("first"); String last = rs.getString("last"); //Display values System.out.print("ID: " + id); System.out.print(", Age: " + age); System.out.print(", First: " + first); System.out.println(", Last: " + last); }
(6)清理环境
应该明确地关闭所有的数据库资源,对依赖于JVM的垃圾收集如下:
//STEP 6:清理环境,关闭连接 rs.close(); stmt.close(); conn.close();
再通过一个完整的JDBC应用程序理解上述6个步骤。基于上面的步骤,完成名为FirstJDBCExample的综合JDBC调用MySQL的应用示例代码,其他数据库连接可以以其作为模板而写出相应的JDBC代码。
//STEP 1. 导入所需包 import java.sql.*; public class FirstJDBCExample { //JDBC驱动名和数据库连接URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/EMP"; //数据库连接凭据 static final String USER = "username"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; Statement stmt = null; try{ //STEP 2: 注册JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); //STEP 3: 打开连接 System.out.println("Connecting to database…"); conn = DriverManager.getConnection(DB_URL,USER,PASS); //STEP 4: 执行查询 System.out.println("Creating statement…"); stmt = conn.createStatement(); String sql; sql = "SELECT id, first, last, age FROM Employees"; ResultSet rs = stmt.executeQuery(sql); //STEP 5: 从结果集中检索数据 while(rs.next()){ //Retrieve by column name int id = rs.getInt("id"); int age = rs.getInt("age"); String first = rs.getString("first"); String last = rs.getString("last"); //Display values System.out.print("ID: " + id); System.out.print(", Age: " + age); System.out.print(", First: " + first); System.out.println(", Last: " + last); } //STEP 6: 清理环境 rs.close(); stmt.close(); conn.close(); }catch(SQLException se){ //处理错误JDBC se.printStackTrace(); }catch(Exception e){ //处理错误Class.forName e.printStackTrace(); }finally{ //最后关闭资源 try{ if(stmt!=null) stmt.close(); }catch(SQLException se2){ }// nothing we can do try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); }//end finally try }//end try System.out.println("Goodbye!"); }//end main }//end FirstJDBCExample
现在可以通过JDK直接来编译上面的例子,当然可以在MyEclipse中完成,具体如下:
C:\>javac FirstJDBCExample.java C:\>
当运行FirstJDBCExample时,会产生以下结果:
C:\>java FirstJDBCExample Connecting to database… Creating statement… ID: 100, Age: 18, First: Zara, Last: Ali ID: 101, Age: 25, First: Mahnaz, Last: Fatma ID: 102, Age: 30, First: Zaid, Last: Khan ID: 103, Age: 28, First: Sumit, Last: Mittal C:\>
注:完整的JDBC使用代码及常见数据库驱动包,参见本书配套代码资料。