`

Java 常用API的运用,效率及技巧十

    博客分类:
  • java
 
阅读更多

10. JDBC类库

有了 JDBC,向各种关系数据库发送 SQL 语句就是一件很容易的事。换言之,有了 JDBC API,就不必为访问 Sybase 数据库专门写一个程序,为访问 Oracle 数据库又专门写一个程序,为访问 Informix 数据库又写另一个程序,等等。您只需用 JDBC API 写一个程序就够了,它可向相应数据库发送 SQL 语句。而且,使用 Java 编程语言编写的应用程序,就无须去忧虑要为不同的平台编写不同的应用程序。将 Java JDBC 结合起来将使程序员只须写一遍程序就可让它在任何平台上运行。

 

下面为常用的处理流程:




 

简单地说,JDBC 可做三件事:

 

1.      与数据库建立连接

2.      发送 SQL 语句

3.      处理结果

 

下列代码段给出了以上三步的基本示例:

Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); Connection conn = DriverManager.getConnection ( "jdbc:oracle:thin:@eai-sol:1521:eai_db", "csc2", "csc2"); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT CONTACTID FROM CONTACTINFO"); while (rs.next()) { long contactID = rs.getLong("CONTACTID"); }

 


 

 

下面对常用的几个类和接口做些简单的说明。

 

DriverManager:

DriverManager类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager 类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。对于简单的应用程序,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。正如名称所示,该方法将建立与数据库的连接。

Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); Connection conn = DriverManager.getConnection ( "jdbc:oracle:thin:@eai-sol:1521:eai_db", "csc2", "csc2");

 


 

 

其中第一句话的作用是在当前的环境中load一个DB Driver, 有人可能觉得奇怪, 这句话执行完之后, 后面怎么知道去用这个Driver呢? 其实DriverManager可以从loadclasses里面找到注册过的driver,然后使用它所找到的第一个可以成功连接到给定 URL 的驱动程序。 第二句话的三个参数分别是URL, User, Password。Driver不一样, URL可能也不一样。

 

Statement:

Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都为在给定连接上执行 SQL 语句的包容器:StatementPreparedStatement(它从 Statement 承而来)和 CallableStatement(它从 PreparedStatement 继承而来)。它们都专用于发送定类型的 SQL 语句: Statement 对象用于执行不带参数的简单 SQL 语句;PreparedStatement 对象用于执行带或不带 IN 参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库已存储过程的调用。

Statement 接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法;而 CallableStatement 添加了处理 OUT 参数的方法。

Ø  创建 Statement 对象
建立了到特定数据库的连接之后,就可用该连接发送 SQL 语句。Statement 对象用 Connection 的方法 createStatement 创建,如下列代码段中所示:
Statement stmt = conn.createStatement();

为了执行 Statement 对象,被发送到数据库的 SQL 语句将被作为参数提供给 Statement 的方法:
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM table1");

 

Ø  使用 Statement 对象执行语句

Statement 接口提供了三种执行 SQL 语句的方法:executeQueryexecuteUpdate execute。使用哪一个方法由 SQL 语句所产生的内容决定。
方法 executeQuery 用于产生单个结果集的语句,例如 SELECT 语句。

方法 executeUpdate 用于执行 INSERTUPDATE DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE DROP TABLEINSERTUPDATE DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

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

 

Ø  语句完成

当连接处于自动提交模式时,其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有结果返回时,即认为已完成。对于返回一个结果集的 executeQuery 方法,在检索完 ResultSet 对象的所有行时该语句完成。对于方法 executeUpdate,当它执行时语句即完成。但在少数调用方法 execute 的情况中,在检索所有结果集或它生成的更新计数之后语句才完成。

 

Ø  关闭 Statement 对象

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

 

ResultSet:

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

结果集一般是一个表,其中有查询所返回的列标题及相应的值。例如,如果查询为 SELECT a, b, c FROM Table1,则结果集将具有如下形式:

a        b         c

-------- --------- --------

12345    Cupertino CA

83472    Redmond   WA

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

 

Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); while (rs.next()) { int i = rs.getInt("a"); String s = rs.getString("b"); Timestamp t = rs.getTimestamp("c"); }

 


 

 

Ø  行和光标

ResultSet 维护指向其当前数据行的光标。每调用一次 next 方法,光标向下移动一行。最初它位于第一行之前,因此第一次调用 next 将把光标置于第一行上,使它成为当前行。随着每次调用 next 导致光标向下移动一行,按照从上至下的次序获取 ResultSet 行。在 ResultSet 对象或其父辈 Statement 对象关闭之前,光标一直保持有效。

 

Ø 

方法 getXXX 提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名为“title”,并将值存储为字符串,则下列任一代码将获取存储在该列中的值:

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

String s = rs.getString(2);

 

 

 

 

注意列是从左至右编号的,并且从列 1 开始。同时,用作 getXXX 方法的输入的列名不区分大小写。 为了代码的可维护性与可读性, 应该禁止用index的方法来取值, 要用读列名的方法, 如上面的第一行取值方法。

 

Ø  数据类型和转换

对于 getXXX 方法,JDBC 驱动程序试图将基本数据转换成指定 Java 类型,然后返回适合的 Java 值。例如,如果 getXXX 方法为 getString,而基本数据库中数据类型为 VARCHAR,则 JDBC 驱动程序将把 VARCHAR 转换成 Java StringgetString 的返回值将为 Java String 对象。

 

Ø  NULL 结果值

要确定给定结果值是否是 JDBC NULL,必须先读取该列,然后使用 ResultSet.wasNull 方法检查该次读取是否返回 JDBC NULL

 

PreparedStatement:

PreparedStatement 接口继承 Statement,并与之在两方面有所不同:

PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句“准备好”。 包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN 参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的 setXXX 方法来提供。

由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。

作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 IN 参数占位符的值。同时,三种方法 execute executeQuery executeUpdate 已被更改以使之不再需要参数。

 

Ø  创建 PreparedStatement 对象

以下的代码段(其中 conn Connection 对象)创建包含带两个 IN 参数占位符的 SQL 语句的 PreparedStatement 对象:

 

 

 

PreparedStatement pstmt =

            conn.prepareStatement("UPDATE table1 SET a = ? WHERE b = ?");

 

 

 

pstmt 对象包含语句 " UPDATE table1 SET a = ? WHERE b = ?",它已发送给 DBMS,并为执行作好了准备。

 

Ø  传递 IN 参数

在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有 Java 类型 long,则使用的方法就是 setLongsetXXX 方法的第一个参数是要设置的参数的序数位置,第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为 123456789,第二个参数设为 100000000

 

 

pstmt.setLong(1, 123456789);

pstmt.setLong(2, 100000000);

 

 

 

CallableStatement:

 

CallableStatement 对象为所有的 DBMS 提供了一种以标准形式调用已储存过程(也就是SP)的方法。已储存过程储存在数据库中。对已储存过程的调用是 CallableStatement 对象所含的内容。有两种形式:一种形式带结果参数,另一种形式不带结果参数。结果参数是一种输出 (OUT) 参数,是已储存过程的返回值。两种形式都可带有数量可变的输入(IN 参数)、输出(OUT 参数)或输入和输出(INOUT 参数)的参数。问号将用作参数的占位符。

 

JDBC 中调用已储存过程的语法如下所示。注意,方括号表示其间的内容是可选项;方括号本身并不是语法的组成部份。

 

 

返回结果参数的过程的语法为:

{call 过程名[(?, ?, ...)]}

 

 

 

{? = call 过程名[(?, ?, ...)]}

 

 

 

 

不带参数的已储存过程的语法类似:

 

 

 

{call 过程名}

 

 

 

 

通常,创建 CallableStatement 对象的人应当知道所用的 DBMS 是支持已储存过程的,并且知道这些过程都是些什么。然而,如果需要检查,多种 DatabaseMetaData 方法都可以提供这样的信息。例如,如果 DBMS 支持已储存过程的调用,则 supportsStoredProcedures 方法将返回 true,而 getProcedures 方法将返回对已储存过程的描述。

 

CallableStatement 继承 Statement 的方法(它们用于处理一般的 SQL 语句),还继承了 PreparedStatement 的方法(它们用于处理 IN 参数)。CallableStatement 中定义的所有方法都用于处理 OUT 参数或 INOUT 参数的输出部分:注册 OUT 参数的 JDBC 类型(一般 SQL 类型)、从这些参数中检索结果,或者检查所返回的值是否为 JDBC NULL

 

Ø  创建 CallableStatement 对象

CallableStatement 对象是用 Connection 方法 prepareCall 创建的。下例创建 CallableStatement 的实例,其中含有对已储存过程 Csc_ GetCustomId调用。该过程有两个变量,但不含结果参数:

   

CallableStatement cstmt = con.prepareCall(

"{call CSC_GetCustomId (?, ?, ?)}");

 

其中 ? 占位符为 IN OUT 还是 INOUT 参数,取决于已储存过程 Csc_ GetCustomId

 

Ø  IN OUT 参数

IN 参数传给 CallableStatement 对象是通过 setXXX 方法完成的。该方法继承自 PreparedStatement。所传入参数的类型决定了所用的 setXXX 方法(例如,用 setFloat 来传入 float 值等)。

如果已储存过程返回 OUT 参数,则在执行 CallableStatement 对象以前必须先注册每个 OUT 参数的 JDBC 类型(这是必需的,因为某些 DBMS 要求 JDBC 类型)。注册 JDBC 类型是用 registerOutParameter 方法来完成的。语句执行完后,CallableStatement getXXX 方法将取回参数值。正确的 getXXX 方法是为各参数所注册的 JDBC 类型所对应的 Java 类型也就是说, registerOutParameter 使用的是 JDBC 类型(因此它与数据库返回的 JDBC 类型匹配),而 getXXX 将之转换为 Java 类型。下面给出CSC中的一个例子:

String sqlSp = "{call CSC_GetCustomId(?, ?, ?)}";

cstmt = conn.prepareCall(sqlSp.toString());

cstmt.registerOutParameter(1, Types.NUMERIC);

cstmt.registerOutParameter(2, Types.NUMERIC);

cstmt.registerOutParameter(3, Types.VARCHAR);

cstmt.execute();

long customerID = cstmt.getLong(1);

long lRet = cstmt.getLong(2);

String sErr = cstmt.getString(3);

 

Ø  INOUT 参数

既支持输入又接受输出的参数(INOUT 参数)除了调用 registerOutParameter 方法外,还要求调用适当的 setXXX 方法(该方法是从 PreparedStatement 继承来的)。setXXX 方法将参数值设置为输入参数,而 registerOutParameter 方法将它的 JDBC 类型注册为输出参数。setXXX 方法提供一个 Java 值,而驱动程序先把这个值转换为 JDBC 值,然后将它送到数据库中。这种 IN 值的 JDBC 类型和提供给 registerOutParameter 方法的 JDBC 类型应该相同。然后,要检索输出值,就要用对应的 getXXX 方法。例如,Java 类型为 byte 的参数应该使用方法 setByte 来赋输入值。应该给 registerOutParameter 提供类型为 TINYINT JDBC 类型,同时应使用 getByte 来检索输出值。下例假设有一个已储存过程 reviseTotal,其唯一参数是 INOUT 参数。方法 setByte 把此参数设为 25,驱动程序将把它作为 JDBC TINYINT 类型送到数据库中。接着,registerOutParameter 将该参数注册为 JDBC TINYINT。执行完该已储存过程后,将返回一个新的 JDBC TINYINT 值。方法 getByte 将把这个新值作为 Java byte 类型检索。

CallableStatement cstmt = con.prepareCall("{call reviseTotal(?)}");

cstmt.setByte(1, 25);

cstmt.registerOutParameter(1, java.sql.Types.TINYINT);

cstmt.executeUpdate();

byte x = cstmt.getByte(1);

 

 

  • 大小: 49.7 KB
分享到:
评论

相关推荐

    java学习的常用API

    Java学习的常用API是开发者日常编码和学习过程中不可或缺的参考资料,尤其对于初学者,理解并掌握这些API至关重要。本资源集合了多个领域的API文档,包括Struts2、Spring、Hibernate、MySQL、Oracle以及一些基础技术...

    javaapi合集

    对于开发者来说,深入理解和熟练运用Java API是提高编程效率和编写高质量代码的关键。通过阅读JDK_API_1_6_zh_CN.CHM这份中文参考文档,开发者可以详细了解到每个类的功能、方法的使用以及参数的含义,从而更好地...

    java 常用工具类

    以上就是关于"java 常用工具类"的一些关键知识点,了解并熟练运用这些工具类可以显著提高我们的编程效率,减少代码量,同时使得程序更易于理解和维护。通过阅读博文链接中的内容,可以深入学习和掌握更多实用技巧。

    JAVA初学者 第6到第8章(接口,异常,常用)

    在"JAVA初学者 第6到第8章"的学习资料中,你将深入理解这两个主题,并了解一些常用的Java编程技巧。 首先,让我们来探讨接口。在Java中,接口是一种完全抽象的类型,它只包含常量和抽象方法的声明,不包含任何实现...

    Java常用方法大全

    以上仅是Java常用方法的一小部分,实际上Java API包含数千个方法。通过深入学习和实践,你可以掌握更多高效编程技巧,提升自己的编程能力。在实际工作中,结合《Java常用方法大全》这样的参考资料,可以随时查阅和...

    java常用正则表达式(转)

    这篇博客“java常用正则表达式(转)”可能详细介绍了Java如何使用正则表达式进行各种操作。虽然没有具体的描述内容,但我们可以从标题和标签中推测,这篇博客可能涵盖了以下几个方面: 1. **正则表达式基础**: -...

    Java编程模式与范例:基础开发技巧

    10. **标准库和API**:Java的标准库提供了大量预定义的类和方法,如日期时间API、网络编程API、XML处理等,熟悉这些API能极大地提高开发效率。 通过对这些知识点的学习和实践,开发者不仅能掌握Java的基础开发技巧...

    Java程序设计技巧1001例

    "Java程序设计技巧1001例"这个资源显然旨在帮助开发者深入理解和运用这些技巧。以下是一些重要的Java编程技巧,涵盖了基础到高级的各个方面。 1. **异常处理**:在Java中,使用try-catch-finally语句块来处理异常是...

    Java 的常用包与数组的复制与排序26

    在Java编程语言中,了解和熟练使用常用的包以及...理解并熟练运用这些知识,将有助于提升Java编程的效率和质量。在实际开发中,还会涉及到更多高级特性和技巧,如多线程、并发控制、设计模式等,都需要不断学习和实践。

    Java编程技巧.pdf

    在Java编程中,掌握一些高效的编码技巧能显著提升代码质量并减少错误。以下是一些关键的知识点,基于提供的文件内容...在实际开发中,灵活运用这些技巧,不仅可以编写出高质量的代码,还能避免常见错误,提升开发效率。

    java程序设计技巧1001例

    在Java程序设计的世界里,掌握各种技巧是提升编程效率和代码质量的关键。"Java程序设计技巧1001例"是一本深入浅出的指南,它涵盖了从基础到高级的各种编程实践,旨在帮助开发者们更好地理解和运用Java语言。在这个...

    JAVA2程序设计实务入门

    这些API的使用是Java编程实践中的常见任务,理解和熟练运用它们能大大提高开发效率。 在描述中提到“实务入门”,这意味着本书不仅会讲解理论知识,还会结合实际案例,提供代码示例和练习,帮助读者将所学知识应用...

    Java常用框架实战教程,包含Activiti,Dubbo

    Java编程语言在IT行业中占有重要地位,而Java开发者在日常工作中常常会接触到各种框架,以提升开发效率和软件质量。本教程重点聚焦于两个著名的Java框架:Activiti和Dubbo,它们分别在业务流程管理和分布式服务领域...

    Java手机短信项目源码Java实用源码整理learns

    3. **Java框架**:Spring、MyBatis、Hibernate等,是企业级开发中常用的工具,掌握它们可以提高开发效率。 4. **Java最佳实践**:包括代码规范、设计模式、重构技巧等,帮助写出更高质量的代码。 5. **开源社区**...

    Java程序设计教程第五版教材(美国)上的例题

    Java程序设计是编程领域中的重要一环,尤其对于初学者来说,掌握其基本概念和实践技巧至关重要。"Java程序设计教程第五版教材(美国)"是一本面向初学者的指南,旨在帮助读者深入理解Java编程语言,并通过实际例题来...

    平安Java考试题库

    10. **数据库**: 数据库操作是Java开发中不可或缺的一部分,可能涉及SQL语句、JDBC API的使用,以及连接池的配置和使用。 11. **测试**: 测试是保证代码质量的重要环节,可能包括单元测试(JUnit)、集成测试和压力...

    Java的常用的正则表达式

    下面我们将深入探讨Java中常用的正则表达式及其应用。 1. **正则表达式基础** - **字符类**:`[]`用于定义一个字符集合,例如`[abc]`匹配'a'、'b'或'c'。 - **量词**:`*`表示零个或多个,`+`表示一个或多个,`?`...

    JAVA范例开发大全

    函数式编程在Java 8之后得到了加强,你可以通过阅读本书了解Lambda表达式、Stream API和方法引用来简化代码,提高代码的可读性和效率。 网络编程也是Java的一大特色,书中可能会涵盖Socket编程,让你学会如何创建...

Global site tag (gtag.js) - Google Analytics