JDBC是一种用于执行SQL语句的JAVA API,它由一组用JAVA语言编写的类和接口组成。通过这些类和接口,JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果。
主要的类和接口:
支持JDBC API的类和主要接口封装在Java.sql(核心API)包和javax.sql(扩展的API)包中。
Java.sql.DriverManager
是唯一的一个服务类,用于管理JDBC驱动程序,提供getConnection方法建立应用程序与数据库连接。当JDBC驱动程序加载到内存时,会自动向JDBC驱动程序进行注册,接着如果有连接数据库的请求,DriverManager类就会用注册的JDBC驱动程序来创建到数据库的连接。一般通过调用Class.forName(String str)来加载驱动程序。
Java.sql.Connection
接口定义到数据库的连接,用于制造Statement对象,提供数据库的信息。一个应用程序可与单个数据库有一个或多个连接,或者可与许多数据库有连接。
Java.sql.Statement
代表SQL语句的接口,通过executeQuery或executeUpdate方法执行一个静态的SQL语句。
Java.sql.ResultSet
接口维护查询得到的一张视图表,它提供了许多维护表记录的方法对数据库进行操作。
Java.sql.SQLException
用于检查并报告用JDBC操作数据库时的错误。JAVA是一种安全性很好的语言,如果在类方法中声明了有例外处理,当在程序中创建对象实例,通过对象实例调用这些方法时都应该提供例外处理。
驱动程序类型:
native 本地的
按层分类
2—层
type 1、2、4,客户直接和数据库会话
3—层
type 3,客户与代表数据库的中间层(如weblogicserver)会话;
选择何种类型的驱动程序主要取决于程序的应用范围。数据库驱动程序是用来解决应用程序与数据库通信问题的。
(1)驱动程序类型一:
将JDBC调用映射到其它类型的数据访问API上,最常用的是JDBC-ODBC桥连接驱动程序,它利用ODBC驱动程序提供JDBC的访问。要注意的是,使用这种类型的驱动程序必须在每个客户机上加载ODBC驱动程序,因此此类型使用于企业内部或者是用JAVA编写的三层结构的应用程序服务器代码。
(2)驱动程序类型二:
是基于本地API,部分用JAVA来编写的驱动程序。直接将应用程序与网络库连接,这样,必须在使用此驱动程序的计算机上安装网络库。这种类型的驱动程序将客户机API上的JDBC调用装换为Oracle、Sybase、Informix、DB2或其它DBMS的调用。
类型2驱动程序的性能优于类型1驱动程序。
(3)驱动程序类型三:
是JDBC网络纯JAVA驱动程序,这种驱动程序将JDBC装换为于DBMS无关的网络协议,此后这种协议将被某个服务器装换为一种DBMS协议。这种网络服务器中间件能够将它的纯JAVA客户机连接到多种不同的数据库上,因为它们仅仅依赖驱动程序和中间件之间的网络协议,而中间件提供数据库到应用程序之间的抽象。
(4)驱动程序类型四:
是本地协议纯JAVA驱动程序,这类驱动程序将JDBC调用转换为DBMS所使用的网络协议,这将允许从客户机直接调用DBMS服务器,获得最大的网络传输速度。
第三种和第四种类型的驱动程序是发展方向。
使用JDBC的过程:
(1) 创建一个JDBC Driver连接实例或DataSource连接实例。
(2) 使用连接实例创建一个连接
(3) 使用JDBC连接创建声明语句
(4) 调用声明语句的executeQuery获得结果集或executeUpdate修改数据库中的数据
(5) 操作结果集的记录
(6) 如果还需要这个连接创建其它结果集,从第3步开始重复
(7) 释放结果集
(8) 释放声明语句
(9) 断开与数据库的连接
(1)加载驱动程序:
Class.forName(类名),就可以将相应的核心类加载到驱动程序管理器中。
(A)加载JDBC-ODBC桥驱动程序
Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);
(B)加载JDBC驱动程序
Class.forName(“jdbc.driver_class_name”);
(C)加载mysql驱动程序
Class.forName(“org.gjt.mm.mysql.Driver”);
(D)加载Oracle驱动程序
Class.forName(“Oracle.jdbc.driver.OracleDriver”);
(2)建立连接
当驱动程序加载成功,就可以操作DriverManager类的getConnection方法建立同数据库的连接,格式如下:
Connectionconn=DriverManger.getConnection(url,login,password);
对于不同的数据库驱动程序,其URL有所不同,但是必须遵从下面两个格式中的一个:
Jdbc:driver-id:database-id
Jdbc:driver-id://host/database-id
例如:
JDBC-ODBC桥驱动程序的格式:jdbc:odbc:数据源名
Mysql jdbc驱动程序的格式:jdbc:mysql://host/test
Oracle jdbc驱动程序的格式:jdbc:oracle:thin:@myhost:1521:ORCL
(1)直接连接(直接在客户端Java代码中打开并维护)
对应于上面提到的1、2、4种驱动程序。使用直接连接时必须在完成对数据库的操作后将连接关闭。否则,太多的连接会导致数据库连接瘫痪。
(2)池连接(被J2EE服务器打开和维护)
(3)声明语句
声明语句的创建:
JDBC提供了三个接口用于向数据库发送SQL语句,它们分别是:Statement,PreparedStatement,CallableStatement。
Connection接口中的三个方法对应于创建上述三个接口实例,分别为:createStatement,preparedStatement,prepareCall。
Statement对象用于发送简单的SQL语句。
PreparedStatement对象用于发送带有一个或多个输入参数的SQL语句,并且它经过预编译,效率要比使用Statament对象高。
CallableStatement对象用于执行SQL存储程序,SQL存储程序是一组通过名称来调用的SQL语句。
普通语句的创建:
String cmd=”select * from BaseInfo”;
Statement stmt=conn.createStatement(cmd);
预编译语句的创建:
String cmd=”select * from BaseInfo where major=?”;
PreparedStatement stmt=conn.prepreadStatement(cmd);
stmt.setString(1,”cs”);
调用存储过程语句的创建:
String cmd=“CALL LIST_ON_MAJOR(‘CS’)”;
CallabelStatement stmt=conn.prepareCall(cmd);
声明语句的执行:
使用SQL语句对数据库执行的操作通常分为两类:一是查询数据库信息;二是操纵数据库数据。
查询数据库信息操作需要返回查询结果集,操纵数据库操作需要返回操纵成功的记录数,所以Statement接口提供两种不同的执行方法完成两类操作。
查询数据库信息:ResultSetrs=stmt.executeQuery(“select *from BaseInfo”);
操纵数据库数据:ResultSetrs=stmt.executeUpdate(“insertinto BaseInfo values(‘02010534’,’xiaoming’,’CS’)”);
声明语句的释放:语句使用完毕,释放语句对象是良好的编程风格:stmt.close();
(4)结果集
结果集类提供了方法getType()检查结果集的类型,方法getConcurrency()检查当前记录的可操作类型。
结果集类型:
TYPE_FORWORD_ONLY:
结果集为只读类型,并且读取顺序从头到尾值读取记录
TYPE_SCROLL_SENSITIVE:
这种结果集是可以滚动的,它的游标能够任意向前,向后和移动到某一个特定的列上去,而且这种结果集对于在其打开过程中数据的变化是敏感的,如果底层的数据改变了,那么新的值就会在结果集中反映出来,这样就可以提供对于底层数据的动态视图,结果集中的成员和行的顺序可以随时改变
TYPE_SCROLL_INSENSITIVE:
insensitive 不敏感的
这种类型的结果集是可以任意滚动,其游标既可以向前又可向后还可以滚动到相对于现在位置的某一个特定的列上。但这种结果集通常不支持底层数据变化的显示,因为结果集被创建时,它的成员、顺序和列的值就已经被确定了。
当前记录集操作类型:
CONCUR_READ_ONLY:结果集是只读的,不能改变当前记录。
CONCUR_UPDATEABLE:结果集可以修改的,可以修改记录的值,插入记录,删除记录。
在进行记录的修改操作时,通常要先检查可操作类型:
if(rs.getCurrency()!=ResultSet.CONCUR_UPDATEABLE)
system.err.println(“Error,cannot change rs”);
游标移动
结果集接口提供了next()方法,使游标向后移动一条记录,previous()方法使游标向前移动一条记录,组合使用这两个方法就可以实现访问结果集任意记录。
遍历一个记录集的方法为:
ResultSet rs=...
while(rs.next()){
... ...
}
访问字段记录:
结果集接口提供了一系列的getXXX方法访问字段的值,XXX表示返回值的类型,调用格式为:
rs.getXXX((index/fieldname)
获得结果集信息:
在操作结果集时,经常需要获得一些额外的信息,如记录数、列名称等等,ResultSetMetaData接口通过元数据(Metadata)提供一个特定结果集的相关信息。
例如:下面代码显示数据库的所有列信息:
ResultSetMetsData MetaData=rs.getMetaData();
int num_columnes=MetaData.getColumnCount();
for (int i=1;i<=numColumns;i++){
Sytem.out.print(“column”);
Sytem.out.print(i); /*列位置*/
Sytem.out.print(“name:”);
Sytem.out.print(MataData.getColumnName(i));/*列名称*/
}
定位记录:
使用absolute()方法可以定位到确定的一条记录上,
例如:定位到第10条记录的语句为:
rs.absolute(10)
删除记录:
使用deleteRow()方法可以删除到当前的一条记录上,
例如:删除第5条记录的语句为:
rs.absolute(5);
rs.deleteRow()
修改记录:
rs.updateXXX(Index, value);
例如:修改所有记录的major字段为”IT”的语句为:
ResultSet rs=...
ResultSetMetaData MetaData=rs.getMetaData();
int index_major=rs.findColumn(“major”);//返回字段major的序号
if(rs.getCurrency()!==Result.CONCUR_UPDATEABLE)
{ system.err.println(“Error,can not change rs ”);
return;
}
while(rs.next())
{ rs.updateString(index_major,”IT”);
}
插入记录:
为插入一条新记录,ResultSet专门创建了一条特殊的记录行,插入一条新纪录的步骤为:
(1)调用movetoInsertRow()方法将游标指向插入行;
(2)使用UpdateXXX()方法修改插入行字段值;
(3)调用insertRow()方法将新记录加入到数据库;
(4)调用movetoCurrentRow()返回当前修改行;
例如增加一条学生记录的语句为:
ResultSet rs=...
if(rs.getCurrency()!==Result.CONCUR_UPDATEABLE)
{ system.err.println(“Error,can not change rs ”);
return;
}
rs.movetoInsertRow();
rs.UpdateString(1,”02010625”);
rs.UpdateString(2,”yulei”);
rs.UpdateString(3,”IT”);
rs.insertRow();
rs.movetoCurrentRow();