??xml version="1.0" encoding="utf-8" standalone="yes"?>2021中文字幕一区亚洲,欧美日韩一区中文字幕,亚洲天堂成人在线 http://www.aygfsteel.com/shuqinpeng/category/2566.htmlJAVA的学?fn)历E?/description>zh-cn Tue, 27 Feb 2007 12:16:36 GMT Tue, 27 Feb 2007 12:16:36 GMT 60 JDBC 指南QCallableStatement http://www.aygfsteel.com/shuqinpeng/articles/9370.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:18:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9370.html http://www.aygfsteel.com/shuqinpeng/comments/9370.html http://www.aygfsteel.com/shuqinpeng/articles/9370.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9370.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9370.html 本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这本书是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版?nbsp; 7.1 概述 CallableStatement 对象为所有的 DBMS 提供?jin)一U以标准形式调用已储存过E的Ҏ(gu)。已储存q程储存在数据库中。对已储存过E的调用?nbsp;CallableStatement 对象所含的内容。这U调用是用一U换码语法来写的Q有两种形式Q一UŞ式带l果参数Q另一UŞ式不带结果参敎ͼ有关换码语法的信息,参见W?nbsp;4 节“语句”)(j)。结果参数是一U输?nbsp;(OUT) 参数Q是已储存过E的q回倹{两UŞ式都可带有数量可变的输入QIN 参数Q、输出(OUT 参数Q或输入和输出(INOUT 参数Q的参数。问号将用作参数的占位符? ?nbsp;JDBC 中调用已储存q程的语法如下所C。注意,Ҏ(gu)可C其间的内容是可选项Q方括号本nq不是语法的l成部䆾? {call q程名[(?, ?, ...)]} q回l果参数的过E的语法为:(x) {? = call q程名[(?, ?, ...)]} 不带参数的已储存q程的语法类|(x) {call q程名} 通常Q创?nbsp;CallableStatement 对象的h应当知道所用的 DBMS 是支持已储存q程的,q且知道q些q程都是些什么。然而,如果需要检查,多种 DatabaseMetaData Ҏ(gu)都可以提供这L(fng)信息。例如,如果 DBMS 支持已储存过E的调用Q则 supportsStoredProcedures Ҏ(gu)返?nbsp;trueQ?nbsp;getProcedures Ҏ(gu)返回对已储存过E的描述? CallableStatement l承 Statement 的方法(它们用于处理一般的 SQL 语句Q,q承了(jin) PreparedStatement 的方法(它们用于处理 IN 参数Q。CallableStatement 中定义的所有方法都用于处理 OUT 参数?nbsp;INOUT 参数的输出部分:(x)注册 OUT 参数?nbsp;JDBC cdQ一?nbsp;SQL cdQ、从q些参数中检索结果,或者检查所q回的值是否ؓ(f) JDBC NULL? 7.1.1 创徏 CallableStatement 对象 CallableStatement 对象是用 Connection Ҏ(gu) prepareCall 创徏的。下例创?nbsp;CallableStatement 的实例,其中含有对已储存q程 getTestData 调用。该q程有两个变量,但不含结果参敎ͼ(x) CallableStatement cstmt = con.prepareCall( "{call getTestData(?, ?)}"); 其中 ? 占位Wؓ(f) IN?nbsp;OUT q是 INOUT 参数Q取决于已储存过E?nbsp;getTestData? 7.1.2 IN ?nbsp;OUT 参数 ?nbsp;IN 参数传给 CallableStatement 对象是通过 setXXX Ҏ(gu)完成的。该Ҏ(gu)l承?nbsp;PreparedStatement。所传入参数的类型决定了(jin)所用的 setXXX Ҏ(gu)Q例如,?nbsp;setFloat 来传?nbsp;float 值等Q? 如果已储存过E返?nbsp;OUT 参数Q则在执?nbsp;CallableStatement 对象以前必须先注册每?nbsp;OUT 参数?nbsp;JDBC cdQ这是必需的,因ؓ(f)某些 DBMS 要求 JDBC cdQ。注?nbsp;JDBC cd是用 registerOutParameter Ҏ(gu)来完成的。语句执行完后,CallableStatement ?nbsp;getXXX Ҏ(gu)取回参数倹{正的 getXXX Ҏ(gu)是ؓ(f)各参数所注册?nbsp;JDBC cd所对应?nbsp;Java cdQ从 JDBC cd?nbsp;Java cd的标准映见 8.6.1 节中的表Q。换a之, registerOutParameter 使用的是 JDBC cdQ因此它与数据库q回?nbsp;JDBC cd匚wQ,?nbsp;getXXX 之转换?nbsp;Java cd? 作ؓ(f)CZQ下qC码先注册 OUT 参数Q执行由 cstmt 所调用的已储存q程Q然后检索在 OUT 参数中返回的倹{方?nbsp;getByte 从第一?nbsp;OUT 参数中取Z?nbsp;Java 字节Q?nbsp;getBigDecimal 从第二个 OUT 参数中取Z?nbsp;BigDecimal 对象Q小数点后面带三位数Q:(x) CallableStatement cstmt = con.prepareCall( "{call getTestData(?, ?)}"); cstmt.registerOutParameter(1, java.sql.Types.TINYINT); cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3); cstmt.executeQuery(); byte x = cstmt.getByte(1); java.math.BigDecimal n = cstmt.getBigDecimal(2, 3); CallableStatement ?nbsp;ResultSet 不同Q它不提供用增量方式(g)索大 OUT 值的Ҏ(gu)机制? 7.1.3 INOUT 参数 既支持输入又接受输出的参敎ͼINOUT 参数Q除?jin)调?nbsp;registerOutParameter Ҏ(gu)外,q要求调用适当?nbsp;setXXX Ҏ(gu)Q该Ҏ(gu)是从 PreparedStatement l承来的Q。setXXX Ҏ(gu)参数D|ؓ(f)输入参数Q?nbsp;registerOutParameter Ҏ(gu)它?nbsp;JDBC cd注册出参数。setXXX Ҏ(gu)提供一?nbsp;Java |而驱动程序先把这个D{换ؓ(f) JDBC |然后它送到数据库中? q种 IN 值的 JDBC cd和提供给 registerOutParameter Ҏ(gu)?nbsp;JDBC cd应该相同。然后,要检索输出|p用对应的 getXXX Ҏ(gu)。例如,Java cd?nbsp;byte 的参数应该用方?nbsp;setByte 来赋输入倹{应该给 registerOutParameter 提供cd?nbsp;TINYINT ?nbsp;JDBC cdQ同时应使用 getByte 来检索输出?nbsp;Q第 8 节“JDBC ?nbsp;Java cd之间的映”将l出详细信息和类型映表Q? 下例假设有一个已储存q程 reviseTotalQ其唯一参数?nbsp;INOUT 参数。方?nbsp;setByte 把此参数设ؓ(f) 25Q驱动程序将把它作ؓ(f) JDBC TINYINT cd送到数据库中。接着QregisterOutParameter 该参数注册?nbsp;JDBC TINYINT。执行完该已储存q程后,返回一个新?nbsp;JDBC TINYINT 倹{方?nbsp;getByte 把q个新g?nbsp;Java byte cd(g)索? CallableStatement cstmt = con.prepareCall( "{call reviseTotal(?)}"); cstmt.setByte(1, 25); cstmt.registerOutParameter(1, java.sql.Types.TINYINT); cstmt.executeUpdate(); byte x = cstmt.getByte(1); 7.1.4 先检索结果,再检?nbsp;OUT 参数 ׃某些 DBMS 的限ӞZ(jin)实现最大的可移植性,先检索由执行 CallableStatement 对象所产生的结果,然后再用 CallableStatement.getXXX Ҏ(gu)来检?nbsp;OUT 参数? 如果 CallableStatement 对象q回多个 ResultSet 对象Q通过调用 execute Ҏ(gu)Q,在检?nbsp;OUT 参数前应先检索所有的l果。这U情况下Qؓ(f)保Ҏ(gu)有的l果都进行了(jin)讉KQ必d Statement Ҏ(gu) getResultSet、getUpdateCount ?nbsp;getMoreResults q行调用Q直C再有l果为止? (g)索完所有的l果后,可?nbsp;CallableStatement.getXXX Ҏ(gu)来检?nbsp;OUT 参数中的倹{? 7.1.5 (g)索作?nbsp;OUT 参数?nbsp;NULL ? q回?nbsp;OUT 参数中的值可能会(x)?nbsp;JDBC NULL。当出现q种情ŞӞ对 JDBC NULL D行{换以?nbsp;getXXX Ҏ(gu)所q回的gؓ(f) null? ?nbsp;falseQ这取决?nbsp;getXXX Ҏ(gu)cd。对?nbsp;ResultSet 对象Q要知道 0 ?nbsp;false 是否源于 JDBC NULL 的唯一Ҏ(gu)Q是用方?nbsp;wasNull q行(g)。如?nbsp;getXXX Ҏ(gu)d的最后一个值是 JDBC NULLQ则该方法返?nbsp;trueQ否则返?nbsp;flase。第 5 节“ResultSet”将l出详细信息? ]]> JDBC 指南QPreparedStatement http://www.aygfsteel.com/shuqinpeng/articles/9369.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:17:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9369.html http://www.aygfsteel.com/shuqinpeng/comments/9369.html http://www.aygfsteel.com/shuqinpeng/articles/9369.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9369.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9369.html 本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版?nbsp; 6.1 概述 ?nbsp;PreparedStatement 接口l承 StatementQƈ与之在两斚w有所不同Q?nbsp; PreparedStatement 实例包含已编译的 SQL 语句。这是使语句“准备好”?nbsp; 包含?nbsp;PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN 参数的值在 SQL 语句创徏时未被指定。相反的Q该语句为每?nbsp;IN 参数保留一个问P“?”)(j)作ؓ(f)占位W。每个问L(fng)值必d该语句执行之前,通过适当?nbsp;setXXX Ҏ(gu)来提供?nbsp; ׃ PreparedStatement 对象已预~译q,所以其执行速度要快?nbsp;Statement 对象。因此,多次执行?nbsp;SQL 语句l常创徏?nbsp;PreparedStatement 对象Q以提高效率? 作ؓ(f) Statement 的子c,PreparedStatement l承?nbsp;Statement 的所有功能。另外它q添加了(jin)一整套Ҏ(gu)Q用于设|发送给数据库以取代 IN 参数占位W的倹{同Ӟ三种Ҏ(gu) execute?nbsp;executeQuery ?nbsp;executeUpdate 已被更改以之不再需要参数。这些方法的 Statement 形式Q接?nbsp;SQL 语句参数的Ş式)(j)不应该用?nbsp;PreparedStatement 对象? 6.1.1 创徏 PreparedStatement 对象 以下的代码段Q其?nbsp;con ?nbsp;Connection 对象Q创建包含带两个 IN 参数占位W的 SQL 语句?nbsp;PreparedStatement 对象Q?nbsp; PreparedStatement pstmt = con.prepareStatement( "UPDATE table4 SET m = ? WHERE x = ?"); pstmt 对象包含语句 "UPDATE table4 SET m = ? WHERE x = ?"Q它已发送给 DBMSQƈ为执行作好了(jin)准备? 6.1.2 传?nbsp;IN 参数 在执?nbsp;PreparedStatement 对象之前Q必设|每?nbsp;? 参数的倹{这可通过调用 setXXX Ҏ(gu)来完成,其中 XXX 是与该参数相应的cd。例如,如果参数h Java cd longQ则使用的方法就?nbsp;setLong。setXXX Ҏ(gu)的第一个参数是要设|的参数的序C|,W二个参数是讄l该参数的倹{例如,以下代码第一个参数设?nbsp;123456789Q第二个参数设ؓ(f) 100000000Q?nbsp; pstmt.setLong(1, 123456789); pstmt.setLong(2, 100000000); 一旦设|了(jin)l定语句的参数|可用它多次执行该语句,直到调用 clearParameters Ҏ(gu)清除它ؓ(f)止? 在连接的~省模式下(启用自动提交Q,当语句完成时自动提交或q原该语句? 如果基本数据库和驱动E序在语句提交之后仍保持q些语句的打开状态,则同一?nbsp;PreparedStatement 可执行多ơ。如果这一点不成立Q那么试N过使用 PreparedStatement 对象代替 Statement 对象来提高性能是没有意义的? 利用 pstmtQ前面创建的 PreparedStatement 对象Q,以下代码例示?jin)如何设|两个参数占位符的值ƈ执行 pstmt 10 ơ。如上所qͼ为做到这一点,数据库不能关?nbsp;pstmt。在该示例中Q第一个参数被讄?nbsp;"Hi"q保持ؓ(f)常数。在 for 循环中,每次都将W二个参数设|ؓ(f)不同的|(x)?nbsp;0 开始,?nbsp;9 l束? pstmt.setString(1, "Hi"); for (int i = 0; i < 10; i++) { pstmt.setInt(2, i); int rowCount = pstmt.executeUpdate(); } 6.1.3 IN 参数中数据类型的一致? setXXX Ҏ(gu)中的 XXX ?nbsp;Java cd。它是一U隐含的 JDBC cdQ一?nbsp;SQL cdQ,因ؓ(f)驱动E序把 Java cd映射为相应的 JDBC cdQ遵循该 JDBC Guide中?.6.2 “映?nbsp;Java ?nbsp;JDBC cd”表中所指定的映)(j)Qƈ该 JDBC cd发送给数据库。例如,以下代码D将 PreparedStatement 对象 pstmt 的第二个参数讄?nbsp;44QJava cd?nbsp;shortQ?nbsp; pstmt.setShort(2, 44); 驱动E序?nbsp;44 作ؓ(f) JDBC SMALLINT 发送给数据库,它是 Java short cd的标准映? E序员的责Q是确保将每个 IN 参数?nbsp;Java cd映射Z数据库所需?nbsp;JDBC 数据cd兼容?nbsp;JDBC cd。不妨考虑数据库需?nbsp;JDBC SMALLINT 的情c(din)如果用方?nbsp;setByte Q则驱动E序?nbsp;JDBC TINYINT 发送给数据库。这是可行的Q因多数据库可从一U相关的cd转换为另一U类型,q且通常 TINYINT 可用?nbsp;SMALLINT 适用的Q何地斏V然而,对于要适用于尽可能多的数据库的应用E序Q最好用与数据库所需的确切的 JDBC cd相应?nbsp;Java cd。如果所需?nbsp;JDBC cd?nbsp;SMALLINTQ则使用 setShort 代替 setByte 应用E序的可UL性更好? 6.1.4 使用 setObject E序员可使用 setObject Ҏ(gu)昑ּ地将输入参数转换为特定的 JDBC cd。该Ҏ(gu)可以接受W三个参敎ͼ用来指定目标 JDBC cd。将 Java Object 发送给数据库之前,驱动E序把它{换ؓ(f)指定?nbsp;JDBC cd? 如果没有指定 JDBC cdQ驱动程序就?x)?nbsp;Java Object 映射到其~省?nbsp;JDBC cdQ参见第 8.6.4 节中的表|(j)Q然后将它发送到数据库。这与常规的 setXXX Ҏ(gu)cMQ在q两U情况下Q驱动程序在值发送到数据库之前,?x)将该值的 Java cd映射为适当?nbsp;JDBC cd。二者的差别在于 setXXX Ҏ(gu)使用?nbsp;Java cd?nbsp;JDBC cd的标准映(参见W?nbsp;8.6.2 节中的表|(j)Q?nbsp;setObject Ҏ(gu)使用?nbsp;Java Object cd?nbsp;JDBC cd的映(参见W?nbsp;8.6.4 节中的表|(j)? Ҏ(gu) setObject 允许接受所?nbsp;Java 对象的能力应用E序更ؓ(f)通用Qƈ可在q行时接受参数的输入。这U情况下Q应用程序在~译时ƈ不清楚输入类型。通过使用 setObjectQ应用程序可接受所?nbsp;Java 对象cd作ؓ(f)输入Qƈ其转换为数据库所需?nbsp;JDBC cd。第 8.6.5 节中的表格显CZ(jin) setObject 可执行的所有可能{换? 6.1.5 ?nbsp;JDBC NULL 作ؓ(f) IN 参数发? setNull Ҏ(gu)允许E序员将 JDBC NULL g?nbsp;IN 参数发送给数据库。但要注意,仍然必须指定参数?nbsp;JDBC cd? 当把 Java null g递给 setXXX Ҏ(gu)Ӟ如果它接?nbsp;Java 对象作ؓ(f)参数Q,也将同样?nbsp;JDBC NULL 发送到数据库。但仅当指定 JDBC cdӞҎ(gu) setObject 才能接受 null 倹{? 6.1.6 发送大?nbsp;IN 参数 setBytes ?nbsp;setString Ҏ(gu)能够发送无限量的数据。但是,有时E序员更喜欢用较?yu)的块传递大型的数据。这可通过?nbsp;IN 参数讄?nbsp;Java 输入来完成。当语句执行ӞJDBC 驱动E序重复调用该输入,d其内容ƈ它们当作实际参数数据传输? JDBC 提供?jin)三U将 IN 参数讄入流的方法:(x)setBinaryStream 用于含有未说明字节的, setAsciiStream 用于含有 ASCII 字符的流Q?nbsp;setUnicodeStream 用于含有 Unicode 字符的流。因为必L定流的总长度,所以这些方法所采用的参数比其它?nbsp;setXXX Ҏ(gu)要多一个。这很有必要Q因Z些数据库在发送数据之前需要知道其ȝ传送大? 以下代码例示?jin)用流作?f) IN 参数来发送文件内容:(x) java.io.File file = new java.io.File("/tmp/data"); int fileLength = file.length(); java.io.InputStream fin = new java.io.FileInputStream(file); java.sql.PreparedStatement pstmt = con.prepareStatement( "UPDATE Table5 SET stuff = ? WHERE index = 4"); pstmt.setBinaryStream (1, fin, fileLength); pstmt.executeUpdate(); 当语句执行时Q将反复调用输入?nbsp;fin 以传递其数据? ]]> JDBC 指南QStatement http://www.aygfsteel.com/shuqinpeng/articles/9367.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:16:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9367.html http://www.aygfsteel.com/shuqinpeng/comments/9367.html http://www.aygfsteel.com/shuqinpeng/articles/9367.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9367.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9367.html 4 - Statement 本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版? 4.1 概述 Statement 对象用于?SQL 语句发送到数据库中。实际上有三U?Statement 对象Q它们都作ؓ(f)在给定连接上执行 SQL 语句的包容器QStatement、PreparedStatementQ它?Statement l承而来Q和 CallableStatementQ它?PreparedStatement l承而来Q。它们都专用于发送特定类型的 SQL 语句Q?Statement 对象用于执行不带参数的简?SQL 语句QPreparedStatement 对象用于执行带或不带 IN 参数的预~译 SQL 语句QCallableStatement 对象用于执行Ҏ(gu)据库已存储过E的调用?BR> Statement 接口提供?jin)执行语句和获取l果的基本方法。PreparedStatement 接口d?jin)处?IN 参数的方法;?CallableStatement d?jin)处?OUT 参数的方法?BR> 4.1.1 创徏 Statement 对象 建立?jin)到特定数据库的q接之后Q就可用该连接发?SQL 语句。Statement 对象?Connection 的方?createStatement 创徏Q如下列代码D中所C:(x) Connection con = DriverManager.getConnection(url, "sunny", ""); Statement stmt = con.createStatement(); Z(jin)执行 Statement 对象Q被发送到数据库的 SQL 语句被作ؓ(f)参数提供l?Statement 的方法:(x) ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2"); 4.1.2 使用 Statement 对象执行语句 Statement 接口提供?jin)三U执?SQL 语句的方法:(x)executeQuery、executeUpdate ?execute。用哪一个方法由 SQL 语句所产生的内容决定?BR> Ҏ(gu) executeQuery 用于产生单个l果集的语句Q例?SELECT 语句?BR> Ҏ(gu) executeUpdate 用于执行 INSERT、UPDATE ?DELETE 语句以及(qing) SQL DDLQ数据定义语aQ语句,例如 CREATE TABLE ?DROP TABLE。INSERT、UPDATE ?DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整敎ͼ指示受媄(jing)响的行数Q即更新计数Q。对?CREATE TABLE ?DROP TABLE {不操作行的语句QexecuteUpdate 的返回值Mؓ(f)零?BR> Ҏ(gu) execute 用于执行q回多个l果集、多个更新计数或二者组合的语句。因为多数程序员不会(x)需要该高功能Q所以本概述后面在单独一节中对其q行介绍?BR> 执行语句的所有方法都关闭所调用?Statement 对象的当前打开l果集(如果存在Q。这意味着在重新执?Statement 对象之前Q需要完成对当前 ResultSet 对象的处理?BR> 应注意,l承?Statement 接口中所有方法的 PreparedStatement 接口都有自己?executeQuery、executeUpdate ?execute Ҏ(gu)。Statement 对象本n不包?SQL 语句Q因而必ȝ Statement.execute Ҏ(gu)提供 SQL 语句作ؓ(f)参数。PreparedStatement 对象q不?SQL 语句作ؓ(f)参数提供l这些方法,因ؓ(f)它们已经包含预编?SQL 语句。CallableStatement 对象l承q些Ҏ(gu)?PreparedStatement 形式。对于这些方法的 PreparedStatement ?CallableStatement 版本Q用查询参数将抛出 SQLException?BR> 4.1.3 语句完成 当连接处于自动提交模式时Q其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有结果返回时Q即认ؓ(f)已完成。对于返回一个结果集?executeQuery Ҏ(gu)Q在(g)索完 ResultSet 对象的所有行时该语句完成。对于方?executeUpdateQ当它执行时语句卛_成。但在少数调用方?execute 的情况中Q在(g)索所有结果集或它生成的更新计C后语句才完成?BR> 有些 DBMS 已存储q程中的每条语句视ؓ(f)独立的语句;而另外一些则整个过E视Z个复合语句。在启用自动提交Ӟq种差别变得非帔R要,因ؓ(f)它媄(jing)响什么时候调?commit Ҏ(gu)。在前一U情况中Q每条语句单独提交;在后一U情况中Q所有语句同时提交?BR> 4.1.4 关闭 Statement 对象 Statement 对象由 Java 垃圾攉E序自动关闭。而作ZU好的编E风|应在不需?Statement 对象时显式地关闭它们。这立即释?DBMS 资源Q有助于避免潜在的内存问题?BR> 4.1.5 Statement 对象中的 SQL 转义语法 Statement 可包含?SQL 转义语法?SQL 语句。{义语法告诉驱动程序其中的代码应该以不同方式处理。驱动程序将扫描M转义语法Qƈ它转换成特定数据库可理解的代码。这使得转义语法?DBMS 无关Qƈ允许E序员用在没有转义语法时不可用的功能?BR> 转义子句p括号和关键字界定Q? {keyword . . . parameters . . . } 该关键字指示转义子句的类型,如下所C?BR> escape 表示 LIKE 转义字符 字符?”和“_”类g SQL LIKE 子句中的通配W(?”匹配零个或多个字符Q而“_”则匚w一个字W)(j)。ؓ(f)?jin)正解释它们,应在其前面加上反斜杠Q“\”)(j)Q它是字W串中的Ҏ(gu)转义字符。在查询末尾包括如下语法卛_指定用作转义字符的字W:(x) {escape 'escape-character'} 例如Q下列查询用反斜杠字符作ؓ(f)转义字符Q查找以下划U开头的标识W名Q? stmt.executeQuery("SELECT name FROM Identifiers WHERE Id LIKE `\_%' {escape `\'}; fn 表示标量函数 几乎所?DBMS 都具有标量值的数倹{字W串、时间、日期、系l和转换函数。要使用q些函数Q可使用如下转义语法Q关键字 fn 后跟所需的函数名?qing)其参数。例如,下列代码调用函数 concat 两个参数连接在一P(x) {fn concat("Hot", "Java")}; 可用下列语法获得当前数据库用户名Q? {fn user()}; 标量函数可能p法稍有不同的 DBMS 支持Q而它们可能不被所有驱动程序支持。各U?DatabaseMetaData Ҏ(gu)列出所支持的函数。例如,Ҏ(gu) getNumericFunctions q回用逗号分隔的数值函数列表,而方?getStringFunctions 返回字W串函数Q等{?BR> 驱动E序{义函数调用映ؓ(f)相应的语法,或直接实现该函数?BR> d、t ?ts 表示日期和时间文?BR> DBMS 用于日期、时间和旉标记文字的语法各不相同。JDBC 使用转义子句支持q些文字的语法的 ISO 标准格式。驱动程序必d转义子句转换?DBMS 表示?BR> 例如Q可用下列语法在 JDBC SQL 语句中指定日期:(x) {d `yyyy-mm-dd'} 在该语法中,yyyy 为年代,mm 为月份,?dd 则ؓ(f)日期。驱动程序将用等L(fng)特定?DBMS 的表C替换这个{义子句。例如,如果 '28- FEB-99' W合基本数据库的格式Q则驱动E序用它替?{d 1999-02-28}?BR> 对于 TIME ?TIMESTAMP 也有cM的{义子句:(x) {t `hh:mm:ss'} {ts `yyyy-mm-dd hh:mm:ss.f . . .'} TIMESTAMP 中的数点后的秒Q?f . . .Q部分可忽略?BR> call ?? = call 表示已存储过E?BR> 如果数据库支持已存储q程Q则可从 JDBC 中调用它们,语法为:(x) {call procedure_name[(?, ?, . . .)]} 或(其中q程q回l果参数Q:(x) {? = call procedure_name[(?, ?, . . .)]} Ҏ(gu)hC其中的内容是可选的。它们不是语法的必要部分?BR> 输入参数可以为文字或参数。有兌l信息,参见 JDBC 指南中第 7 节,“CallableStatement”?BR> 可通过调用Ҏ(gu) DatabaseMetaData.supportsStoredProcedures (g)查数据库是否支持已存储过E?BR> oj 表示外部q接 外部q接的语法ؓ(f) {oj outer-join} 其中 outer-join 形式? table LEFT OUTER JOIN {table / outer-join} ON search-condition 外部q接属于高功能。有兛_们的解释可参?SQL 语法。JDBC 提供?jin)三U?DatabaseMetaData Ҏ(gu)用于定驱动E序支持哪些外部q接cdQsupportsOuterJoins、supportsFullOuterJoins ?supportsLimitedOuterJoins?BR> Ҏ(gu) Statement.setEscapeProcessing 可打开或关闭{义处理;~省状态ؓ(f)打开。当性能极ؓ(f)重要ӞE序员可能想关闭它以减少处理旉。但通常它将Z打开状态。应注意Q?setEscapeProcessing 不适用?PreparedStatement 对象Q因为在调用该语句前它就可能已被发送到数据库。有关预~译的信息,参见 PreparedStatement?BR> 4.1.6 使用Ҏ(gu) execute execute Ҏ(gu)应该仅在语句能返回多?ResultSet 对象、多个更新计数或 ResultSet 对象与更新计数的l合时用。当执行某个已存储过E或动态执行未?SQL 字符Ԍ卛_用程序程序员在编译时未知Q时Q有可能出现多个l果的情况,管q种情况很少见。例如,用户可能执行一个已存储q程Q?CallableStatement 对象 - 参见W?135 늚 CallableStatementQ,q且该已存储q程可执行更斎ͼ然后执行选择Q再q行更新Q再q行选择Q等{。通常使用已存储过E的人应知道它所q回的内宏V?BR> 因ؓ(f)Ҏ(gu) execute 处理非常规情况,所以获取其l果需要一些特D处理ƈ不为怪。例如,假定已知某个q程q回两个l果集,则在使用Ҏ(gu) execute 执行该过E后Q必调用方?getResultSet 获得W一个结果集Q然后调用适当?getXXX Ҏ(gu)获取其中的倹{要获得W二个结果集Q需要先调用 getMoreResults Ҏ(gu)Q然后再调用 getResultSet Ҏ(gu)。如果已知某个过E返回两个更新计敎ͼ则首先调用方?getUpdateCountQ然后调?getMoreResultsQƈ再次调用 getUpdateCount?BR> 对于不知道返回内容,则情冉|为复杂。如果结果是 ResultSet 对象Q则Ҏ(gu) execute q回 trueQ如果结果是 Java intQ则q回 false。如果返?intQ则意味着l果是更新计数或执行的语句是 DDL 命o(h)。在调用Ҏ(gu) execute 之后要做的第一件事情是调用 getResultSet ?getUpdateCount。调用方?getResultSet 可以获得两个或多?ResultSet 对象中第一个对象;或调用方?getUpdateCount 可以获得两个或多个更新计CW一个更新计数的内容?BR> ?SQL 语句的结果不是结果集Ӟ则方?getResultSet 返?null。这可能意味着l果是一个更新计数或没有其它l果。在q种情况下,判断 null 真正含义的唯一Ҏ(gu)是调用方?getUpdateCountQ它?yu)返回一个整数。这个整Cؓ(f)调用语句所影响的行敎ͼ如果?-1 则表C结果是l果集或没有l果。如果方?getResultSet 已返?nullQ表C结果不?ResultSet 对象Q,则返回?-1 表示没有其它l果。也是_(d)当下列条件ؓ(f)真时表示没有l果Q或没有其它l果Q:(x) ((stmt.getResultSet() == null) && (stmt.getUpdateCount() == -1)) 如果已经调用Ҏ(gu) getResultSet q处理了(jin)它返回的 ResultSet 对象Q则有必要调用方?getMoreResults 以确定是否有其它l果集或更新计数。如?getMoreResults q回 trueQ则需要再ơ调?getResultSet 来检索下一个结果集。如上所qͼ如果 getResultSet q回 nullQ则需要调?getUpdateCount 来检?null 是表C结果ؓ(f)更新计数q是表示没有其它l果?BR> ?getMoreResults q回 false Ӟ它表C SQL 语句q回一个更新计数或没有其它l果。因此需要调用方?getUpdateCount 来检查它是哪一U情c(din)在q种情况下,当下列条件ؓ(f)真时表示没有其它l果Q? ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1)) 下面的代码演CZ(jin)一U方法用来确认已讉K调用Ҏ(gu) execute 所产生的全部结果集和更新计敎ͼ(x) stmt.execute(queryStringWithUnknownResults); while (true) { int rowCount = stmt.getUpdateCount(); if (rowCount > 0) { // 它是更新计数 System.out.println("Rows changed = " + count); stmt.getMoreResults(); continue; } if (rowCount == 0) { // DDL 命o(h)?0 个更?BR>System.out.println(" No rows changed or statement was DDL command"); stmt.getMoreResults(); continue; } // 执行到这里,证明有一个结果集 // 或没有其它结?BR> ResultSet rs = stmt.getResultSet; if (rs != null) { . . . // 使用元数据获得关于结果集列的信息 while (rs.next()) { . . . // 处理l果 stmt.getMoreResults(); continue; } break; // 没有其它l果
]]>JDBC 指南QResultSet http://www.aygfsteel.com/shuqinpeng/articles/9368.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:16:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9368.html http://www.aygfsteel.com/shuqinpeng/comments/9368.html http://www.aygfsteel.com/shuqinpeng/articles/9368.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9368.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9368.html 本概q是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版?nbsp; 5.1 概述 ResultSet 包含W合 SQL 语句中条件的所有行Qƈ且它通过一?nbsp;get Ҏ(gu)Q这?nbsp;get Ҏ(gu)可以讉K当前行中的不同列Q提供了(jin)对这些行中数据的讉K。ResultSet.next Ҏ(gu)用于Ud?nbsp;ResultSet 中的下一行,使下一行成为当前行? l果集一般是一个表Q其中有查询所q回的列标题?qing)相应的倹{例如,如果查询?nbsp;SELECT a, b, c FROM Table1Q则l果集将h如下形式Q?nbsp; a b c -------- --------- -------- 12345 Cupertino CA 83472 Redmond WA 83492 Boston MA 下面的代码段是执?nbsp;SQL 语句的示例。该 SQL 语句返回行集合Q其中列 1 ?nbsp;intQ列 2 ?nbsp;StringQ而列 3 则ؓ(f)字节数组Q?nbsp; 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); } 5.1.1 行和光标 ResultSet l护指向其当前数据行的光标。每调用一?nbsp;next Ҏ(gu)Q光标向下移动一行。最初它位于W一行之前,因此W一ơ调?nbsp;next 把光标|于W一行上Q它成为当前行。随着每次调用 next D光标向下Ud一行,按照从上至下的次序获?nbsp;ResultSet 行? ?nbsp;ResultSet 对象或其父辈 Statement 对象关闭之前Q光标一直保持有效? ?nbsp;SQL 中,l果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用Ҏ(gu) getCursorName 获得光标名? 注意Q不是所有的 DBMS 都支持定位更新和删除。可使用 DatabaseMetaData.supportsPositionedDelete ?nbsp;supportsPositionedUpdate Ҏ(gu)来检查特定连接是否支持这些操作。当支持q些操作ӞDBMS/驱动E序必须保适当锁定选定行,以定位更新不会(x)D更新异常或其它ƈ发问题? 5.1.2 ? Ҏ(gu) getXXX 提供?jin)获取当前行中某列值的途径。在每一行内Q可按Q何次序获取列倹{但Z(jin)保证可移植性,应该从左臛_获取列|q且一ơ性地d列倹{? 列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名ؓ(f)“title”,q将值存储ؓ(f)字符Ԍ则下列Q一代码获取存储在该列中的|(x) String s = rs.getString("title"); String s = rs.getString(2); 注意列是从左臛_~号的,q且从列 1 开始。同Ӟ用作 getXXX Ҏ(gu)的输入的列名不区分大写? 提供使用列名q个选项的目的是Z(jin)让在查询中指定列名的用户可用相同的名字作ؓ(f) getXXX Ҏ(gu)的参数。另一斚wQ如?nbsp;select 语句未指定列名(例如在“select * from table1”中或列是导出的Ӟ(j)Q则应该使用列号。这些情况下Q用户将无法切知道列名? 有些情况下,SQL 查询q回的结果集中可能有多个列具有相同的名字。如果列名用?nbsp;getXXX Ҏ(gu)的参敎ͼ?nbsp;getXXX 返回第一个匹配列名的倹{因而,如果多个列具有相同的名字Q则需要用列索引来确保检索了(jin)正确的列倹{这Ӟ使用列号效率要稍微高一些? 关于 ResultSet 中列的信息,可通过调用Ҏ(gu) ResultSet.getMetaData 得到。返回的 ResultSetMetaData 对象给出其 ResultSet 对象各列的编受类型和属性? 如果列名已知Q但不知其烦(ch)引,则可用方?nbsp;findColumn 得到其列受? 5.1.3 数据cd和{? 对于 getXXX Ҏ(gu)QJDBC 驱动E序试图基本数据{换成指定 Java cdQ然后返回适合?nbsp;Java 倹{例如,如果 getXXX Ҏ(gu)?nbsp;getStringQ而基本数据库中数据类型ؓ(f) VARCHARQ则 JDBC 驱动E序把 VARCHAR 转换?nbsp;Java String。getString 的返回值将?nbsp;Java String 对象? 下表昄?jin)允许?nbsp;getXXX 获取?nbsp;JDBC cd?qing)推荐用它获取?nbsp;JDBC cdQ通用 SQL cdQ。小写的 x 表示允许 getXXX Ҏ(gu)获取该数据类型;大写?nbsp;X 表示对该数据cd推荐使用 getXXX Ҏ(gu)。例如,除了(jin) getBytes ?nbsp;getBinaryStream 之外的Q?nbsp;getXXX Ҏ(gu)都可用来获取 LONGVARCHAR |但是推荐Ҏ(gu)q回的数据类型?nbsp;getAsciiStream ?nbsp;getUnicodeStream Ҏ(gu)。方?nbsp;getObject Q何数据类型返回ؓ(f) Java Object。当基本数据cd是特定于数据库的抽象cd或当通用应用E序需要接受Q何数据类型时Q它是非常有用的? 可?nbsp;ResultSet.getXXX Ҏ(gu)获取常见?nbsp;JDBC 数据cd?nbsp; 5.1.4 寚w常大的行g用流 ResultSet 可以获取L大的 LONGVARBINARY ?nbsp;LONGVARCHAR 数据。方?nbsp;getBytes ?nbsp;getString 数据返回ؓ(f)大的块(最大ؓ(f) Statement.getMaxFieldSize 的返回|(j)。但是,以较?yu)的固定块获取非常大的数据可能?x)更方便,而这可通过?nbsp;ResultSet c返?nbsp;java.io.Input 来完成。从该流中可分块d数据。注意:(x)必须立即讉Kq些,因ؓ(f)在下一ơ对 ResultSet 调用 getXXX 时它们将自动关闭Q这是由于基本实现对大块数据讉K有限Ӟ(j)?nbsp; JDBC API h三个获取的Ҏ(gu)Q分别具有不同的q回|(x) getBinaryStream q回只提供数据库原字节而不q行M转换的流? getAsciiStream q回提供单字?nbsp;ASCII 字符的流? getUnicodeStream q回提供双字?nbsp;Unicode 字符的流? 注意Q它不同?nbsp;Java ,后者返回无cd字节q可Q例如)(j)通用?nbsp;ASCII ?nbsp;Unicode 字符? 下列代码演示?nbsp;getAsciiStream 的用法:(x) java.sql.Statement stmt = con.createStatement(); ResultSet r = stmt.executeQuery("SELECT x FROM Table2"); // 现在?nbsp;4K 块大获取列 1 l果Q? byte buff = new byte[4096]; while (r.next()) { Java.io.InputStream fin = r.getAsciiStream(1); for (;;) { int size = fin.read(buff); if (size == -1) { // 到达末? break; } // 新填充的缓冲区发送到 ASCII 输出:(x) output.write(buff, 0, size); } } 5.1.5 NULL l果? 要确定给定结果值是否是 JDBC NULLQ必dd该列Q然后?nbsp;ResultSet.wasNull Ҏ(gu)(g)查该ơ读取是否返?nbsp;JDBC NULL? 当?nbsp;ResultSet.getXXX Ҏ(gu)d JDBC NULL ӞҎ(gu) wasNull 返回下列g一Q?nbsp; Java null |(x)对于q回 Java 对象?nbsp;getXXX Ҏ(gu)Q例?nbsp;getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject {)(j)? 零|(x)对于 getByte、getShort、getInt、getLong、getFloat ?nbsp;getDouble? false |(x)对于 getBoolean? 5.1.6 可选结果集或多l果? 通常使用 executeQueryQ它q回单个 ResultSetQ或 executeUpdateQ它可用于Q何数据库修改语句Qƈq回更新行数Q可执行 SQL 语句。但有些情况下,应用E序在执行语句之前不知道该语句是否返回结果集。此外,有些已存储过E可能返回几个不同的l果集和/或更新计数? Z(jin)适应q些情况QJDBC 提供?jin)一U机Ӟ允许应用E序执行语句Q然后处理由l果集和更新计数l成的Q意集合。这U机制的原理是首先调用一个完全通用?nbsp;execute Ҏ(gu)Q然后调用另外三个方法,getResultSet、getUpdateCount ?nbsp;getMoreResults。这些方法允许应用程序一ơ一个地研究语句l果Qƈ定l定l果?nbsp;ResultSet q是更新计数? 用户不必关闭 ResultSetQ当产生它的 Statement 关闭、重新执行或用于从多l果序列中获取下一个结果时Q该 ResultSet 被 Statement 自动关闭? ]]> JDBC 指南QDriverManager http://www.aygfsteel.com/shuqinpeng/articles/9365.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:12:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9365.html http://www.aygfsteel.com/shuqinpeng/comments/9365.html http://www.aygfsteel.com/shuqinpeng/articles/9365.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9365.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9365.html 3.1 概述 DriverManager cL JDBC 的管理层Q作用于用户和驱动程序之间? 它跟t可用的驱动E序Qƈ在数据库和相应驱动程序之间徏立连接? 另外QDriverManager cM处理诸如驱动E序d旉限制?qing)登录和跟踪消息的显C等事务? 对于单的应用E序Q一般程序员需要在此类中直接用的唯一Ҏ(gu)?nbsp;DriverManager.getConnection。正如名U所C,该方法将建立与数据库的连接。JDBC 允许用户调用 DriverManager 的方法getDriver、getDrivers ?nbsp;registerDriver ?nbsp;Driver 的方法connect。但多数情况下,?nbsp;DriverManager cȝ理徏立连接的l节Z{? 3.1.1 跟踪可用驱动E序 DriverManager cd含一?nbsp;Driver c,它们已通过调用Ҏ(gu) DriverManager.registerDriver 对自p行了(jin)注册。所?nbsp;Driverc都必须包含有一个静(rn)态部分。它创徏该类的实例,然后在加载该实例?nbsp;DriverManager c进行注册。这P用户正常情况下将不会(x)直接调用 DriverManager.registerDriverQ而是在加载驱动程序时由驱动程序自动调用。加?nbsp;Driver c,然后自动?nbsp;DriverManager 中注册的方式有两U:(x) 通过调用Ҏ(gu) Class.forName。这显式地加蝲驱动E序cR由于这与外部设|无养I因此推荐使用q种加蝲驱动E序的方法。以下代码加载类 acme.db.DriverQ?nbsp; Class.forName("acme.db.Driver"); 如果?nbsp;acme.db.Driver ~写为加载时创徏实例Qƈ调用以该实例为参数的DriverManager.registerDriverQ本该如此)(j)Q则它在DriverManager 的驱动程序列表中Qƈ可用于创接? 通过驱动程序添加到 java.lang.System 的属?nbsp;jdbc.drivers 中这是一个由 DriverManager cd载的驱动E序cd的列表,由冒号分隔:(x)初始?nbsp;DriverManager cLQ它搜烦(ch)pȝ属?nbsp;jdbc.driversQ? 如果用户已输入了(jin)一个或多个驱动E序Q则 DriverManager cd试图加蝲它们? 以下代码说明E序员如何在 ~/.hotjava/properties 中输入三个驱动程序类Q启动时QHotJava 把它加载到pȝ属性列表中Q:(x) jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver; ?nbsp;DriverManager Ҏ(gu)的第一ơ调用将自动加蝲q些驱动E序cR? 注意Q加载驱动程序的W二U方法需要持久的预设环境。如果对q一点不能保证,则调用方?nbsp;Class.forName 昑ּ地加载每个驱动程序就昑־更ؓ(f)安全。这也是引入特定驱动E序的方法,因ؓ(f)一?nbsp;DriverManager c被初始化,它将不再(g)查jdbc.drivers 属性列表? 在以上两U情况中Q新加蝲?nbsp;Driver c都要通过调用 DriverManager.registerDriverc进行自我注册。如上所qͼ加蝲cL自动执行这一q程? ׃安全斚w的原因,JDBC 理层将跟踪哪个cd载器提供哪个驱动E序。这P?nbsp;DriverManager cL开q接Ӟ它仅使用本地文gpȝ或与发出q接h的代码相同的cd载器提供的驱动程序? 3.1.2 建立q接 加蝲 Driver cdƈ?nbsp;DriverManager cM注册后,它们卛_用来与数据库建立q接。当调用DriverManager.getConnection Ҏ(gu)发出q接hӞDriverManager 检查每个驱动程序,查看它是否可以徏立连接? 有时可能有多?nbsp;JDBC 驱动E序可以与给定的 URL q接。例如,与给定远E数据库q接Ӟ可以使用 JDBC-ODBC 桥驱动程序、JDBC 到通用|络协议驱动E序或数据库厂商提供的驱动程序。在q种情况下测试驱动程序的序臛_重要Q因?nbsp;DriverManager 用它所扑ֈ的第一个可以成功连接到l定 URL 的驱动程序? 首先 DriverManager 试图按注册的序使用每个驱动E序Qjdbc.drivers 中列出的驱动E序L先注册)(j)。它?yu)蟩q代码不可信ȝ驱动E序Q除非加载它们的源与试图打开q接的代码的源相同? 它通过轮流在每个驱动程序上调用Ҏ(gu) Driver.connectQƈ向它们传递用户开始传递给Ҏ(gu)DriverManager.getConnection ?nbsp;URL 来对驱动E序q行试Q然后连接第一个认?gu)?nbsp;URL 的驱动程序? q种Ҏ(gu)初看h效率不高Q但׃不可能同时加载数十个驱动E序Q因此每ơ连接实际只需几个q程调用和字W串比较? 以下代码是通常情况下用驱动E序Q例?nbsp;JDBC-ODBC 桥驱动程序)(j)建立q接所需所有步骤的CZQ?nbsp; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加蝲驱动E序 String url = "jdbc:odbc:fred"; DriverManager.getConnection(url, "userID", "passwd"); ]]> JDBC 指南Q连?/title> http://www.aygfsteel.com/shuqinpeng/articles/9364.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:11:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9364.html http://www.aygfsteel.com/shuqinpeng/comments/9364.html http://www.aygfsteel.com/shuqinpeng/articles/9364.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9364.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9364.html and Annotated Reference 》这本书中摘引来的。JavaSoft 目前正在准备q本书。这本书是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版? 2.1 概述 Connection 对象代表与数据库的连接。连接过E包括所执行?nbsp;SQL 语句和在该连接上所q回的结果。一个应用程序可与单个数据库有一个或多个q接Q或者可与许多数据库有连接? 2.1.1 打开q接与数据库建立q接的标准方法是调用 DriverManager.getConnection Ҏ(gu)。该Ҏ(gu)接受含有某个 URL 的字W串。DriverManager c(x谓的 JDBC 理层)(j)尝试找到可与那?nbsp;URL 所代表的数据库q行q接的驱动程序。DriverManager cd有已注册?nbsp;Driver cȝ清单。当调用Ҏ(gu) getConnection Ӟ它将(g)查清单中的每个驱动程序,直到扑ֈ可与 URL 中指定的数据库进行连接的驱动E序为止。Driver 的方?nbsp;connect 使用q个 URL 来徏立实际的q接? 用户可绕q?nbsp;JDBC 理层直接调?nbsp;Driver Ҏ(gu)。这在以下特D情况下很有用Q当两个驱动器可同时q接到数据库中,而用户需要明地选用其中特定的驱动器。但一般情况下Q让 DriverManager cd理打开q接q种事将更ؓ(f)单? 下述代码昄如何打开一个与位于 URL "jdbc:odbc:wombat" 的数据库的连接。所用的用户标识Wؓ(f) "oboy" Q口令ؓ(f) "12Java"Q?nbsp; String url = "jdbc:odbc:wombat"; Connection con = DriverManager.getConnection(url, "oboy", "12Java"); 2.1.2 一般用法的 URL׃ URL 常引h淆,我们先对一?nbsp;URL 作简单说明,然后再讨?nbsp;JDBC URL? URLQ统一资源定位W)(j)提供?nbsp;Internet 上定位资源所需的信息。可它惌Z个地址? URL 的第一部䆾指定?jin)访问信息所用的协议Q后面L跟着冒号。常用的协议?nbsp;"ftp"Q代表“文件传输协议”)(j)?nbsp;"http" Q代表“超文本传输协议”)(j)? 如果协议?nbsp;"file"Q表C源是在某个本地文件系l上而非?nbsp;Internet 上(下例用于表示我们所描述的部分;它ƈ?nbsp;URL 的组成部分)(j)? ftp://javasoft.com/docs/JDK-1_apidocs.zip http://java.sun.com/products/jdk/CurrentRelease file:/home/haroldw/docs/books/tutorial/summary.html URL 的其余部份(冒号后面的)(j)l出?jin)数据资源所处位|的有关信息。如果协议是 fileQ则 URL 的其余部份是文g的\径。对?nbsp;ftp ?nbsp;http 协议QURL 的其余部份标识了(jin)Lq可选地l出某个更详的地址路径。例如,以下?nbsp;JavaSoft 主页?nbsp;URL。该 URL 只标识了(jin)LQ?nbsp; http://java.sun.com从该主页开始浏览,可以进到许多其它的|页中,其中之一是 JDBC 主页。JDBC 主页?nbsp;URL 更ؓ(f)具体Q它看v来类|(x) http://java.sun.com/products/jdbc 2.1.3 JDBC URL JDBC URL 提供?jin)一U标识数据库的方法,可以使相应的驱动E序能识别该数据库ƈ与之建立q接。实际上Q驱动程序编E员决定用什?nbsp;JDBC URL 来标识特定的驱动E序。用户不必关?j)如何来形?nbsp;JDBC URLQ他们只M用与所用的驱动E序一h供的 URL 卛_。JDBC 的作用是提供某些U定Q驱动程序编E员在构造他们的 JDBC URL 时应该遵循这些约定? ׃ JDBC URL 要与各种不同的驱动程序一起用,因此q些U定应非常灵zR首先,它们应允怸同的驱动E序使用不同的方案来命名数据库。例如, odbc 子协议允许(但ƈ不是要求Q?nbsp;URL 含有属性倹{第二,JDBC URL 应允?dng)R动程序编E员一切所需的信息编入其中。这样就可以让要与给定数据库对话?nbsp;applet 打开数据库连接,而无要求用户去做Q何系l管理工作? W三Q?nbsp;JDBC URL 应允许某U程度的间接性。也是_(d)JDBC URL 可指向逻辑L或数据库名,而这U逻辑L或数据库名将ql命名系l动态地转换为实际的名称。这可以使系l管理员不必特定主机声明ؓ(f) JDBC 名称的一部䆾。网l命名服务(例如 DNS?nbsp;NIS ?nbsp;DCE Q有多种,而对于用哪U命名服务ƈ无限制。JDBC URL 的标准语法如下所C。它׃部分l成Q各部分间用冒号分隔Q?nbsp; jdbc:< 子协?nbsp;>:< 子名U?nbsp;>JDBC URL 的三个部分可分解如下Q?nbsp;jdbc ─ 协议。JDBC URL 中的协议L jdbc? <子协?gt; ─ 驱动E序名或数据库连接机Ӟq种机制可由一个或多个驱动E序支持Q的名称。子协议名的典型CZ?nbsp;"odbc"Q该名称是ؓ(f)用于指定 ODBC 风格的数据资源名U的 URL 专门保留的。例如,Z(jin)通过 JDBC-ODBC 桥来讉K某个数据库,可以用如下所C的 URLQ?nbsp; jdbc:odbc:fred本例中,子协议ؓ(f) "odbc"Q子名称 "fred" 是本地ODBC 数据资源? 如果要用|络命名服务Q这?nbsp;JDBC URL 中的数据库名UC必是实际名称Q,则命名服务可以作为子协议。例如,可用如下所C的 URL Q?nbsp; jdbc:dcenaming:accounts-payable本例中,?nbsp;URL 指定?jin)本?nbsp;DCE 命名服务应该? 数据库名U?nbsp;"accounts-payable" 解析为更为具体的可用于连接真实数据库的名U?lt;子名U?gt; ─ 一U标识数据库的方法。子名称可以依不同的子协议? 变化。它q可以有子名U的子名Uͼ含有驱动E序~程员所选的M内部语法Q。用子名称的目的是为定位数据库提供_的信息。前 例中Q因?nbsp;ODBC 提供其余部份的信息Q因此用 "fred" 已_。然而,位于q程服务器上的数据库需要更多的信息。例如,如果数据库是通过 Internet 来访问的Q则?nbsp;JDBC URL 中应网l地址作ؓ(f)子名U的一部䆾包括q去Q且必须遵@如下所C的标准 URL 命名U定Q?nbsp; //L?端口/子协议假?nbsp;"dbnet" 是个用于某个主接到 Internet 上的协议Q则 JDBC URL cMQ? jdbc:dbnet://wombat:356/fred 2.1.4 "odbc" 子协? 子协?nbsp;odbc 是一U特D情c(din)它是ؓ(f)用于指定 ODBC 风格的数据资源名U的 URL 而保留的Qƈh下列Ҏ(gu):(x)允许在子名称Q数据资源名Uͼ(j)后面指定L多个属性倹{odbc 子协议的完整语法为:(x) jdbc:odbc:< 数据资源名称 >[;< 属性名 >=< 属性?nbsp;>]*因此Q以下都是合法的 jdbc:odbc 名称Q?nbsp;jdbc:odbc:qeor7jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey2.1.5 注册子协议驱动程序编E员可保留某个名UC之用作 JDBC URL 的子协议名? ?nbsp;DriverManager cd此名U加到已注册的驱动程序清单中ӞZ保留该名U的驱动E序应能识别该名Uƈ与它所标识的数据库建立q接。例如,odbc 是ؓ(f) JDBC- ODBC 桥而保留的。示例之二,假设有个 Miracle 公司Q它可能?x)?nbsp;"miracle" 注册接到?nbsp;Miracle DBMS 上的 JDBC 驱动E序的子协议Q从而其他人都无法使用q个名称。JavaSoft 目前作ؓ(f)非正式代理负责注?nbsp;JDBC 子协议名U。要注册某个子协议名Uͼ请发送电(sh)子邮件到下述地址Q?nbsp; jdbc@wombat.eng.sun.com2.1.6 发?nbsp;SQL 语句q接一旦徏立,可用来向它所涉及(qing)的数据库传?nbsp;SQL 语句。JDBC对可被发送的 SQL 语句cd不加M限制。这提供了(jin)很大的灵zL,卛_怋用特定的数据库语句或甚至于非 SQL 语句。然而,它要 求用戯p责确保所涉及(qing)的数据库可以处理所发送的 SQL 语句Q否则将自食其果。例如,如果某个应用E序试图向不支持储存E序?nbsp;DBMS 发送储存程序调用,׃(x)p|q将抛出异常。JDBC 要求驱动E序应至能提供 ANSI SQL-2 Entry Level 功能才可是W合 JDBC 标准TM 的。这意味着用户臛_可信赖这一标准U别的功能。JDBC 提供?jin)三个类Q用于向数据库发?nbsp;SQL 语句。Connection 接口中的三个Ҏ(gu)可用于创些类的实例。下面列?gu)些类及(qing)其创徏?gu)Q?nbsp; Statement ─ 由方?nbsp;createStatement 所创徏。Statement 对象用于发送简单的 SQL 语句?nbsp; PreparedStatement ─ 由方?nbsp;prepareStatement 所创徏? PreparedStatement 对象用于发送带有一个或多个输入参数Q?nbsp;IN 参数Q? ?nbsp;SQL 语句。PreparedStatement 拥有一l方法,用于讄 IN 参数的倹{? 执行语句Ӟq些 IN 参数被送到数据库中。PreparedStatement 的实 例扩展了(jin) Statement Q因此它们都包括?nbsp;Statement 的方法? PreparedStatement 对象有可能比 Statement 对象的效率更高,因ؓ(f)它已被预~译qƈ存放在那以供来使用?nbsp; CallableStatement ─ 由方?nbsp;prepareCall 所创徏。CallableStatement 对象 用于执行 SQL 储存E序 ─ 一l可通过名称来调用(p函数的调用那P(j)? SQL 语句。CallableStatement 对象?nbsp;PreparedStatement 中承了(jin)用于 处理 IN 参数的方法,而且q增加了(jin)用于处理 OUT 参数?nbsp;INOUT 参数的方法?nbsp; 以下所列提供的Ҏ(gu)可以快速决定应用哪?nbsp;Connection Ҏ(gu)来创Z同类型的 SQL 语句Q?nbsp;createStatement Ҏ(gu)用于Q? 单的 SQL 语句Q不带参敎ͼ(j) prepareStatement Ҏ(gu)用于Q?nbsp;带一个或多个 IN 参数?nbsp;SQL 语句 l常被执行的?nbsp;SQL 语句 prepareCall Ҏ(gu)用于Q?nbsp;调用已储存过E?.1.7 事务事务׃个或多个q样的语句组成:(x)q些语句已被执行、完成ƈ被提交或q原。当调用Ҏ(gu) commit ?nbsp;rollback Ӟ当前事务卛_q束,另一个事务随卛_始? ~省情况下,新连接将处于自动提交模式。也是_(d)当执行完语句后,自动对那个语句调用 commit Ҏ(gu)。这U情况下Q由于每个语句都是被单独提交的,因此一个事务只׃个语句组成。如果禁用自动提交模式,事务要{到 commit ?nbsp;llback Ҏ(gu)被显式调用时 才结束,因此它将包括上一ơ调?nbsp;commit ?nbsp;rollback Ҏ(gu)以来所有执行过的语句。对于第二种情况Q事务中的所有语句将作ؓ(f)l来提交或还原。方?nbsp;commit ?nbsp;SQL 语句Ҏ(gu)据库所做的M更改成ؓ(f)怹性的Q它q将释放事务持有的全部锁。而方?nbsp;rollback 弃去那些更攏V? 有时用户在另一个更改生效前不想让此更改生效。这可通过用自动提交q将两个更新l合在一个事务中来达到。如果两个更新都是成? Q则调用 commit Ҏ(gu)Q从而两个更新l果成ؓ(f)怹性的Q如果其中之一或两个更新都p|?jin),则调?nbsp;rollback Ҏ(gu)Q以值恢复ؓ(f)q行更新之前的倹{? 大多?nbsp;JDBC 驱动E序都支持事务。事实上Q符?nbsp;JDBC 的驱动程序必L持事务。DatabaseMetaData l出的信息描q?nbsp;DBMS 所提供的事务支持水q?.1.8 事务隔离U别如果 DBMS 支持事务处理Q它必须有某U途径来管理两个事务同时对一个数据库q行操作时可能发生的冲突。用户可指定事务隔离U别Q以指明 DBMS 应该花多大精力来解决潜在冲突。例如,当事务更改了(jin)某个D第二个事务却在该更改被提交或还原前d该值时该怎么?nbsp;假设W一个事务被q原后,W二个事务所d的更改值将是无效的Q那么是否可允许q种冲突Q?nbsp;JDBC 用户可用以下代码来指C?nbsp;DBMS 允许在D提交前读取该|“dirty d”)(j)Q其?nbsp;con 是当前连接:(x) con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED); 事务隔离U别高Qؓ(f)避免冲突所q_֊也就多。Connection 接口定义?jin)五U,其中最低别指定了(jin)Ҏ(gu)׃支持事务Q而最高别则指定当事务在Ҏ(gu)个数据库q行操作ӞM其它事务不得寚w个事务正在读取的数据q行M更改。通常Q隔ȝ别越高,应用E序执行的速度也就慢Q由于用于锁定的资源耗费增加?jin),而用户间的ƈ发操作减了(jin)Q。在军_采用什么隔ȝ别时Q开发h员必d性能需求和数据一致性需求之间进行权衡。当?dng)实际所能支持的U别取决于所涉及(qing)?nbsp;DBMS 的功能? 当创?nbsp;Connection 对象Ӟ其事务隔ȝ别取决于驱动E序Q但通常是所涉及(qing)的数据库的缺省倹{用户可通过调用 setIsolationLevelҎ(gu)来更改事务隔ȝ别。新的别将在该q接q程的剩余时间内生效。要惛_改变一个事务的事务隔离U别Q必d该事务开始前q行讄Qƈ在该事务l束后进行复位。我们不提倡在事务的中途对事务隔离U别q行更改Q因立卌?nbsp;commit Ҏ(gu)的调用,使在此之前所作的M更改变成怹性的?img src ="http://www.aygfsteel.com/shuqinpeng/aggbug/9364.html" width = "1" height = "1" /> ]]> JDBC 指南Q介l?/title> http://www.aygfsteel.com/shuqinpeng/articles/9363.htmlPS@JAVA PS@JAVA Fri, 05 Aug 2005 02:10:00 GMT http://www.aygfsteel.com/shuqinpeng/articles/9363.html http://www.aygfsteel.com/shuqinpeng/comments/9363.html http://www.aygfsteel.com/shuqinpeng/articles/9363.html#Feedback 0 http://www.aygfsteel.com/shuqinpeng/comments/commentRss/9363.html http://www.aygfsteel.com/shuqinpeng/services/trackbacks/9363.html JavaSoft 目前正在准备q本书。这是一本教E,同时也是 JDBC 的重要参考手册,它将作ؓ(f) Java pd的组成部份在 1997 q春季由 Addison-Wesley 出版公司出版?nbsp; 1.1 什么是 JDBCTMQ?nbsp; JDBCTM 是一U用于执?nbsp;SQL 语句?nbsp;JavaTM APIQ有意思的是,JDBC 本n是个商标名而不是一个羃写字Q然而,JDBC 常被认ؓ(f)是代?nbsp;“Java 数据库连?nbsp;(Java Database Connectivity)”)(j)。它׃l用 Java ~程语言~写的类和接口组成。JDBC 为工?数据库开发h员提供了(jin)一个标准的 APIQ他们能够用纯 Java API 来编写数据库应用E序?nbsp; 有了(jin) JDBCQ向各种关系数据库发?nbsp;SQL 语句是一件很Ҏ(gu)的事。换a之,有了(jin) JDBC APIQ就不必?nbsp;Sybase 数据库专门写一个程序,?nbsp;Oracle 数据库又专门写一个程序,?nbsp;Informix 数据库又写另一个程序,{等。?zhn)只需?nbsp;JDBC API 写一个程序就够了(jin)Q它可向相应数据库发?nbsp;SQL 语句。而且Q?nbsp;Java ~程语言~写的应用程序,无d忧虑要ؓ(f)不同的^台编写不同的应用E序。将 Java ?nbsp;JDBC l合hɽE序员只d一遍程序就可让它在Mq_上运行?nbsp; Java h坚固、安全、易于用、易于理解和可从|络上自动下载等Ҏ(gu),是编写数据库应用E序的杰?gu)a。所需要的只是 Java 应用E序与各U不同数据库之间q行对话的方法。?nbsp;JDBC 正是作ؓ(f)此种用途的机制?nbsp; JDBC 扩展?nbsp;Java 的功能。例如,?nbsp;Java ?nbsp;JDBC API 可以发布含有 applet 的网,而该 applet 使用的信息可能来自远E数据库。企业也可以?nbsp;JDBC 通过 Intranet 所有职员连C个或多个内部数据库中Q即使这些职员所用的计算机有 Windows?nbsp;Macintosh ?nbsp;UNIX {各U不同的操作pȝQ。随着来多的程序员开始?nbsp;Java ~程语言Q对?nbsp;Java中便捷地讉K数据库的要求也在日益增加?nbsp; MIS 理员们都喜?nbsp;Java ?nbsp;JDBC 的结合,因ؓ(f)它信息传播变得Ҏ(gu)和经。企业可l箋使用它们安装好的数据库,q能便捷地存取信息,即ɘq些信息是储存在不同数据库管理系l上。新E序的开发期很短。安装和版本控制大为简化。程序员可只~写一遍应用程序或只更Cơ,然后它攑ֈ服务器上Q随后Q何h都可得到最新版本的应用E序。对于商务上的销售信息服务, Java ?nbsp;JDBC 可ؓ(f)外部客户提供获取信息更新的更好方法?nbsp; 1.1.1 JDBC 的用途是什么? 单地_(d)JDBC 可做三g事:(x) 与数据库建立q接Q?nbsp; 发?nbsp;SQL 语句Q?nbsp; 处理l果?nbsp; 下列代码D늻Z(jin)以上三步的基本示例:(x) Connection con = DriverManager.getConnection ( "jdbc:odbc:wombat", "login", "password"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); while (rs.next()) { int x = rs.getInt("a"); String s = rs.getString("b"); float f = rs.getFloat("c"); } 1.1.2 JDBC 是一U低U?nbsp;API Q是高 API 的基 JDBC 是个“低U”接口,也就是说Q它用于直接调用 SQL 命o(h)。在q方面它的功能极佻Iq比其它的数据库q接 API 易于使用Q但它同时也被设计ؓ(f)一U基接口Q在它之上可以徏立高U接口和工具。高U接口是“对用户友好的”接口,它用的是一U更易理解和更ؓ(f)方便?nbsp;APIQ这U?nbsp;API 在幕后被转换?nbsp;JDBC q样的低U接口。在~写本文Ӟ正在开发两U基?nbsp;JDBC 的高U?nbsp;APIQ?nbsp; 一U用?nbsp;Java 的嵌入式 SQL。至已l有一个提供者计划编写它。DBMS 实现 SQLQ一U专门设计来与数据库联合使用的语a。JDBC 要求 SQL 语句必须作ؓ(f) String 传给 Java Ҏ(gu)。相反,嵌入?nbsp;SQL 预处理器允许E序员将 SQL 语句直接与Java 混在一起用。例如,可在 SQL 语句中?nbsp;Java 变量Q用以接受或提供 SQL 倹{然后,嵌入?nbsp;SQL 预处理器通过 JDBC 调用把这U?nbsp;Java/SQL 的合物转换?nbsp;Java?nbsp; 关系数据库表?nbsp;Java cȝ直接映射。JavaSoft 和其它提供者都声称要实现该 API。在q种“对?关系”映中Q表中的每行对应于类的一个实例,而每列的值对应于该实例的一个属性。于是,E序员可直接?nbsp;Java 对象q行操作Q存取数据所需?nbsp;SQL 调用在“掩盖下”自动生成。此外还可提供更复杂的映,例如多个表中的行结合进一?nbsp;Java cM?nbsp; 随着Z?nbsp;JDBC 的兴日益增涨,来多的开发h员一直在使用Z JDBC 的工P以ɽE序的编写更加容易。程序员也一直在~写力图使最l用户对数据库的讉K变得更ؓ(f)单的应用E序。例如,应用E序可提供一个选择数据库Q务的菜单? d被选定后,应用E序给出提C及(qing)I白供填写执行选定d所需的信息。所需信息输入后,应用E序自动调用所需的SQL 命o(h)。在q样一U程序的协助下,即用户Ҏ(gu)不懂 SQL 的语法,也可以执行数据库d?nbsp; 1.1.3 JDBC ?nbsp;ODBC 和其?nbsp;API 的比?nbsp; 目前QMicrosoft ?nbsp;ODBCQ开攑ּ数据库连接)(j)API 可能是用最q的、用于访问关pL据库的编E接口。它能在几乎所有^Cq接几乎所有的数据库。ؓ(f)什?nbsp;Java 不?nbsp;ODBCQ?nbsp; 对这个问题的回答是:(x)Java 可以使用 ODBCQ但最好是?nbsp;JDBC 的帮助下?nbsp;JDBC-ODBC 桥的形式使用Q这一Ҏ(gu)们稍后再说。现在的问题已变成:(x)“ؓ(f)什么需?nbsp;JDBC”? 回答如下Q?nbsp; ODBC 不适合直接?nbsp;Java 中用,因ؓ(f)它?nbsp;C 语言接口。从 Java 调用本地 C 代码在安全性、实现、坚固性和E序的自动移植性方面都有许多缺炏V?nbsp; ?nbsp;ODBC C API ?nbsp;Java API 的字面翻译是不可取的。例如,Java 没有指针Q?nbsp;ODBC 却对指针用得很广泛(包括很容易出错的指针 "void *"Q。?zhn)可以?nbsp;JDBC 惌成被转换为面向对象接口的 ODBCQ而面向对象的接口?nbsp;Java E序员来说较 易于接收?nbsp; ODBC 很难学。它把简单和高功能混在一P而且即对于单的查询Q其选项也极为复杂。相反,JDBC 量保证单功能的便性,而同时在必要时允怋用高U功能?nbsp; 启用“纯 Java ”机刉要象 JDBC q样?nbsp;Java API。如果?nbsp;ODBCQ就必须手动地将 ODBC 驱动E序理器和驱动E序安装在每台客h上。如果完全用 Java ~写 JDBC 驱动E序?nbsp;JDBC 代码在所?nbsp;Java q_上(从网l计机到大型机Q都可以自动安装、移植ƈ保证安全性?nbsp; MQJDBC API 对于基本?nbsp;SQL 抽象和概忉|一U自然的 Java 接口。它建立?nbsp;ODBC 上而不是从零开始。因此,熟?zhn)?nbsp;ODBC 的程序员发?nbsp;JDBC 很容易用。JDBC 保留?nbsp;ODBC 的基本设计特征;事实上,两种接口都基?nbsp;X/Open SQL CLIQ调用接口Q。它们之间最大的区别在于QJDBC ?nbsp;Java 风格与优点ؓ(f)基础q进行优化,因此更加易于使用?nbsp; 最q,Microsoft 又引q了(jin) ODBC 之外的新 APIQ?nbsp;RDO?nbsp;ADO ?nbsp;OLE DB。这些设计在许多斚w?nbsp;JDBC 是相同的Q即它们都是面向对象的数据库接口且基于可?nbsp;ODBC 上实现的cR但在这些接口中Q我们未看见有特别的功能使我们要转而选择它们来替?nbsp;ODBCQ尤其是?nbsp;ODBC 驱动E序已徏立v较ؓ(f)完善的市(jng)场的情况下。它们最多也是?nbsp;ODBC 上加?jin)一U装饰而已。这q不是说 JDBC 不需要从其最初的版本再发展了(jin)Q然而,我们觉得大部份的新功能应归入诸如前一节中所q的对象/关系映射和嵌入式 SQL q样的高U?nbsp;API?nbsp; 1.1.4 两层模型和三层模?nbsp; JDBC API 既支持数据库讉K的两层模型,同时也支持三层模型?nbsp; 在两层模型中QJava applet 或应用程序将直接与数据库q行对话。这需要一?nbsp;JDBC 驱动E序来与所讉K的特定数据库理pȝq行通讯。用L(fng) SQL 语句被送往数据库中Q而其l果被送回l用戗数据库可以位于另一台计机上,用户通过|络q接C面。这叫做客h/服务器配|,其中用户的计机为客hQ提供数据库的计机为服务器。网l可以是 IntranetQ它可将公司职员q接hQ,也可以是 Internet?nbsp; 在三层模型中Q命令先是被发送到服务的“中间层”,然后由它?yu)?nbsp;SQL 语句发送给数据库。数据库?nbsp;SQL 语句q行处理q将l果送回C间层Q中间层再将l果送回l用戗MIS ȝ们都发现三层模型很吸引hQ因为可用中间层来控制对公司数据的访问和可作的的更新的种cR中间层的另一个好处是Q用户可以利用易于用的高 APIQ而中间层把它{换ؓ(f)相应的低U调用。最后,许多情况下三层结构可提供一些性能上的好处?nbsp; 到目前ؓ(f)止,中间层通常都用 C ?nbsp;C++ q类语言来编写,q些语言执行速度较快。然而,随着最优化~译器(它把 Java字节代码转换为高效的特定于机器的代码Q的引入Q用 Java 来实C间层变得越来越实际。这是一个很大的q步Q它使h们可以充分利?nbsp;Java 的诸多优点(如坚固、多U程和安全等特征Q。JDBC 对于?nbsp;Java 的中间层来访问数据库非常重要?nbsp; 1.1.5 SQL 的一致?nbsp; l构化查询语a (SQL) 是访问关pL据库的标准语a。困难之处在于:(x)虽然大多数的 DBMS Q数据库理pȝQ对其基本功能都使用?jin)标准Ş式?nbsp;SQLQ但它们却不W合最qؓ(f)更高U的功能定义的标?nbsp;SQL 语法或语义。例如,q所有的数据库都支持储存E序或外部连接,那些支持q一功能的数据库又相互不一致。h们希?nbsp;SQL 中真正标准的那部份能够进行扩展以包括来多的功能。但同时 JDBC API 又必L持现有的 SQL?nbsp; JDBC API 解决q个问题的一U方法是允许Q何查询字W串一直传到所涉及(qing)?nbsp;DBMS 驱动E序上。这意味着应用E序可以使用L多的 SQL 功能Q但它必dq样的风险:(x)有可能在某些 DBMS 上出错。事实上Q应用程序查询甚至不一定要?nbsp;SQLQ或者说它可以是个ؓ(f)特定?nbsp;DBMS 设计?nbsp;SQL 的专用派生物Q例如,文档或图象查询)(j)?nbsp; JDBC 处理 SQL 一致性问题的W二U方法是提供 ODBC 风格的{义子句。这在 4.1.5 节“语句对象中?nbsp;SQL 转义语法”中讨论?nbsp; 转义语法为几个常见的 SQL 分歧提供?jin)一U标准的 JDBC 语法。例如,Ҏ(gu)期文字和已储存过E的调用都有转义语法?nbsp; 对于复杂的应用程序,JDBC 用第三种Ҏ(gu)来处?nbsp;SQL 的一致性问题。它利用 DatabaseMetaData 接口来提供关?nbsp;DBMS 的描q性信息,从而应用E序能适应每个 DBMS 的要求和功能?nbsp; ׃ JDBC API 用作开发高U数据库讉K工具?nbsp;API 的基 APIQ因此它q必L意其所有上层徏{的一致性。“符?nbsp;JDBC 标准TM" 代表用户可依赖的 JDBC 功能的标准别。要使用q一说明Q驱动程序至必L?nbsp;ANSI SQL-2 Entry LevelQANSI SQL-2 代表国国家标准局 1992 q所采用的标准。Entry Level 代表 SQL 功能的特定清单)(j)。驱动程序开发h员可?nbsp;JDBC API 所带的试工具包来定他们的驱动程序是否符合这些标准?nbsp; “符?nbsp;JDBC 标准TM?nbsp;表示提供者的 JDBC 实现已经通过?nbsp;JavaSoft 提供的一致性测试。这些一致性测试将(g)?nbsp;JDBC API 中定义的所有类和方法是否都存在Qƈ可能地(g)查程序是否具?nbsp;SQL Entry Level 功能。当?dng)q些试q不完全Q而且 JavaSoft 目前也无意对各提供者的实现q行标。但q种一致性定义的可?nbsp;JDBC 实现提供一定的可信度。随着来多的数据库提供者、连接提供者、Internet 提供者和应用E序~程员对 JDBC API 的接受,JDBC 也正q速成?nbsp;Java 数据库访问的标准?nbsp; 1.2 JDBC 产品 在编写本文时Q有几个Z JDBC 的品已开发完毕或正在开发中。当?dng)本节中的信息很快成时信息。因此,有关最新的信息Q请查阅 JDBC 的网站,可通过从以?nbsp;URL 开始浏览找刎ͼ(x) http://java.sun.com/products/jdbc 1.2.1 JavaSoft 框架 JavaSoft 提供三种 JDBC 产品lgQ它们是 Java 开发工具包 (JDK) 的组成部份:(x) JDBC 驱动E序理器, JDBC 驱动E序试工具包,?nbsp; JDBC-ODBC 桥?nbsp; JDBC 驱动E序理器是 JDBC 体系l构的支柱。它实际上很,也很单;其主要作用是?nbsp;Java 应用E序q接到正的JDBC 驱动E序上,然后即退出?nbsp; JDBC 驱动E序试工具包ؓ(f)?nbsp;JDBC 驱动E序q行(zhn)的E序提供一定的可信度。只有通过 JDBC 驱动E序试包的驱动E序才被认ؓ(f)是符?nbsp;JDBC 标准TM 的?nbsp; JDBC-ODBC 桥 ODBC 驱动E序可被用作 JDBC 驱动E序。它的实Cؓ(f) JDBC 的快速发展提供了(jin)一条途径Q其长远目标提供一U访问某些不常见?nbsp;DBMSQ如果对q些不常见的 DBMS 未实?nbsp;JDBCQ?nbsp;的方法?nbsp; 1.2.2 JDBC 驱动E序的类?nbsp; 我们目前所知晓?nbsp;JDBC 驱动E序可分Z下四个种c:(x) JDBC-ODBC 桥加 ODBC 驱动E序QJavaSoft 桥品利?nbsp;ODBC 驱动E序提供 JDBC 讉K。注意,必须?nbsp;ODBC 二进制代码(许多情况下还包括数据库客h代码Q加载到使用该驱动程序的每个客户Z。因此,q种cd的驱动程序最适合于企业网Q这U网l上客户机的安装不是主要问题Q,或者是?nbsp;Java ~写的三层结构的应用E序服务器代码?nbsp;本地 API - 部䆾?nbsp;Java 来编写的驱动E序Q?nbsp;q种cd的驱动程序把客户?nbsp;API 上的 JDBC 调用转换?nbsp;Oracle?nbsp;Sybase、Informix、DB2 或其?nbsp;DBMS 的调用。注意,象桥驱动E序一Pq种cd的驱动程序要求将某些二进制代码加载到每台客户Z?nbsp; JDBC |络U?nbsp;Java 驱动E序Q这U驱动程序将 JDBC 转换Z DBMS 无关的网l协议,之后q种协议又被某个服务器{换ؓ(f)一U?nbsp;DBMS 协议。这U网l服务器中间件能够将它的U?nbsp;Java 客户接到多种不同的数据库上。所用的具体协议取决于提供者。通常Q这是最为灵zȝ JDBC 驱动E序。有可能所有这U解x案的提供者都提供适合?nbsp;Intranet 用的产品。ؓ(f)?jin)ɘq些产品也支?nbsp;Internet 讉KQ它们必d?nbsp;Web 所提出的安全性、通过防火墙的讉K{方面的额外要求。几家提供者正?nbsp;JDBC 驱动E序加到他们现有的数据库中间件品中?nbsp; 本地协议U?nbsp;Java 驱动E序Q这U类型的驱动E序?nbsp;JDBC 调用直接转换?nbsp;DBMS 所使用的网l协议。这允总客户机机器上直接调用 DBMS 服务器,?nbsp;Intranet 讉K的一个很实用的解x法。由于许多这L(fng)协议都是专用的,因此数据库提供者自己将是主要来源,有几家提供者已在着手做qg事了(jin)?nbsp; 最后,我们预计W?nbsp;3? c驱动程序将成ؓ(f)?nbsp;JDBC 讉K数据库的首选方法。第 1? c驱动程序在直接的纯 Java 驱动E序q没有上?jng)前?x)作ؓ(f)q渡Ҏ(gu)来用。对W?nbsp;1? c驱动程序可能会(x)有一些变U(下表中未列出Q,q些变种要求有连接器Q但通常q些是更加不可取的解x案。第 3? c驱动程序提供了(jin) Java 的所有优点,包括自动安装Q例如,通过使用 JDBC 驱动E序?nbsp;applet applet来下载该驱动E序Q?nbsp; 下表昄?jin)?nbsp;4 U类型的驱动E序?qing)其属性:(x) 驱动E序U类 U?nbsp;JAVAQ?nbsp;|络协议 1 - JDBC-OCBC ?nbsp;?nbsp;直接 2 - Z本地 API ?nbsp;?nbsp;直接 3 - JDBC |络?nbsp;?nbsp;要求q接?nbsp; 4 - Z本地协议?nbsp;?nbsp;直接 1.2.3 JDBC 驱动E序的获?nbsp; 在编写本文时Q已有几十个属于U类的驱动程序,卛_?nbsp;Javasoft 桥联合用的 1: ODBC 驱动E序的驱动程序。有大约十多个属于种c?nbsp;2 的驱动程序是?nbsp;DBMS 的本?nbsp;API 为基~写的。只有几个属于种c?nbsp;3 的驱动程序。目前至有 2 个属于种c?nbsp;4 的驱动程序,但到 1997 q底Q我们预计主要的 DBMS 都会(x)有种c?nbsp;4 的驱动程序?nbsp; 要获取关于驱动程序的最C息,h?nbsp;JDBC 的网站,其网址为:(x) http:// java.sun.com/products/jdbc。提供第 3 U驱动程序的首批提供者是 SCO、Open Horizon、Visigenic ?nbsp;WebLogic。JavaSoft 和数据库q接的领先提供?nbsp;Intersolv合作研制?nbsp;JDBC-ODBC 桥和 JDBC 驱动E序试工具包?nbsp; 1.2.4 其它产品 各种 JDBC 应用E序的开发工h在开发中。请注意查阅 JavaSoft |页以得到更C息?nbsp; ]]>
վ֩ģ壺
Ͻ |
פ |
|
ϲ |
ɣ |
Ϻӿ |
|
|
|
߷ |
|
|
|
ˮ |
Ϫ |
³ |
|
Դ |
|
|
|
|
ɽ |
|
Ȩ |
|
|
ʼ |
|
|
|
կ |
Ҵ |
Ȫ |
|
Դ |
ɽ |
¤ |
Ȫ |
ƫ |
ױ |