| 
| 
| J2EE 应用程序中的数据管理和数据持久性 |  
| 时间:2014-05-04 10:04:10  来源:不详  作者:佚名 |  
| | 本文分析了在 Java 平 连接(JDBC)。尽管本质上
 系统时,JDBC 轻而易举地
 Shankar Itchapurapu 对序
 JDBC 是您的最佳选择的原
 
 | 台上可用的两个数据管理策略: 这两种数据管理策略并不存在孰
 得以胜出。在本文中,Java 开
 列化和 JDBC都进行了介绍,并
 因。
 
 | Java 对象序列化和 Java 数据库 优孰劣的问题,但在管理企业信息
 发人员 G.V.B. Subrahmanyam 和
 通过讨论和实例来向您展示了
 
 
 | 
 
 | 当您正在建立企业信息 对于所有业务而言,数据都
 重要性是无论如何强调都不
 
 | 系统时,需要确保以某种有效的 是独一无二的最大资产。所有软
 过分的。
 
 | 方式存储、检索和显示企业数据。 件系统都涉及数据,因此,数据的
 
 
 | 
 
 | 应用程序的数据管理功 们是:建立、检索、更新
 范围之内,始终如一地、成
 。换句话说,管理数据意味
 CRUD 操作,在软件的生命
 
 | 能包括四个基本操作,通常也需 和 删除(即 CRUD)。管理在企
 功地执行 CRUD 操作,而不必频
 着开发稳健的、可扩展和可维护
 期中能够以一致的方式执行操作
 
 | 要对企业数据执行这四个操作,它 业系统的数据涉及在很长一段时间
 繁地更改实际执行这些操作的代码
 的软件系统,以确保成功地进行
 。
 
 | 
 
 | 本文讨论了 J2EE 中的两种可用数据 JDBC)。我们将查看这两种方法的优缺点
 定实现中,策略的可用性取决于项目的范
 上下文(驱动系统/子系统运行时的值的
 并不适合于企业系统,其数据需要用一种
 速浏览 Java 对象序列化,然后查看 JDB
 所缺乏的一些关键特性的。
 
 | 管理策略:Java 对象序列化和 Java 数据库连接( 。这两种数据管理策略实质上不存在孰优孰劣。在特
 围(出现在系统环境中的活动的活动范围),系统的
 集合),以及其他的外部因素。然而,Java 序列化
 定义良好的结构(如RDBMS)来组织。我们首先将快
 C 更重要的一些方面,从而了解后者是如何实现前者
 
 
 | 
 
 | 本文并不打算对 Java 对象序列化或 ,请回顾参考资料小节。
 
 | 者 JDBC 进行全面介绍。有关这两项技术的更多信息 
 
 | 
 
 
 | 对象序列化是最简单的 的线性序列的过程。对象图
 非暂态实例属性以字节的形
 中的值。如果一个 Java 对
 口,该接口具有如下所示的
 
 | Java 持久性策略。对象序列化 是作为对象继承、关联和聚合的
 式被写入到持久存储中。实例属
 象是可序列化的,那么它至少必
 结构:
 
 | 是一个将对象图平面化为一个字节 结果而实现的一些关系式。对象的
 性的值就是执行时间序列化时内存
 须实现 java.io.Serializable 接
 
 
 | 
 
 | public interface Serializable | 
 
 | 您可以看到,java.io.Serializable 接口。它告诉 Java 运行时环境,该实现
 例类。
 
 | 接口并没有声明任何方法。它是一个记号或者标记 类是可序列化的。列表 1 显示实现该接口的一个示
 
 
 | 
 
 | 列表 1. MySerializableObject.java | 
 
 | import java.io.Serializable; | 
 
 | public class MySeria 
 | lizableObject extends MySupe 
 | rClass implements Serializable 
 | 
 | private String property1 = null; | 
 | private String property2 = null; | 
 
 | public String getProperty1() | 
 
 | public void setProperty1(String val) | 
 | public String getProperty2() | 
 
 | public void setProperty2(String val) | 
 | private void w 
 | riteObject(ObjectOutputStrea 
 | m out) 
 | 
 | out.writeObject (getProperty1 ()); | 
 | out.writeObject (getProperty2 ()); | 
 
 | private void r 
 | eadObject (ObjectInputStream 
 | in) 
 | 
 | throws IOException, ClassN 
 | otFoundException 
 | 
 | setProperty1 ((String) in 
 | .readObject ()); 
 | 
 | setProperty2 
 | ((String) in.readObject ()); 
 | 
 
 | 无需自己实现 writeOb 环境具有使这些方法可用的
 您自己的实现。
 
 | ject(...) 和 readObject(...) 默认实现。然而,您可以重写这
 
 
 | 方法来执行序列化;Java 运行时 些方法,提供如何存储对象状态的
 
 
 | 
 
 | 关于序列化,您需要记住一些要点。 被引用类)都将被序列化。其次, Seria
 ,除非已经特别声明它们为暂态,或者已
 只序列化那些可序列化的实例变量。如果
 
 | 首先,在序列化期间,整个对象图(即,所有父类和 lizable 类的所有实例变量自身都应该是可序列化的
 经重写 writeObject(...) 和 readObject(...) 来
 违反了后一规则,在运行时将出现一个异常。
 
 | 
 
 | 每个后续 J2SE 版本都 ObjectOutputStream and O
 法。通常,一个序列化的流
 其他对象可以对它进行后向
 用。非共享的读写方法允许
 象克隆但开销更少的效果。
 
 | 对对象序列化系统进行少量的增 bjectInputStream 增加 writeU
 只包含任何给定对象的一个序列
 引用。通常期望序列化一个对象
 对象作为新的、独一无二的对象
 
 
 | 加。J2SE 1.4 也相应地向 nshared() and readUnshared()方
 化实例,并且共享对该对象引用的
 独立于其他对象可能维护的任何引
 被序列化,从而获得一个类似于对
 
 
 | 
 
 
 | 序列化涉及到将对象图 销。通常,对应用程序而言
 
 | 从内存具体化到持久存储(例如 ,序列化并不是最佳选择:
 
 | 硬盘)中。这涉及到大量 I/O 开 
 
 | 
 
 
 | 序列化的字节流只对 Java 语言是可 的,许多应用程序要与其他应用程序共同
 
 | 读的。这是一个重大缺陷,因为企业系统通常是异构 处理相同的数据。
 
 | 
 
 
 | 没有一个用来从序列化对象图中检索获取数据的查询语言。 | 
 
 
 | 序列化本身并不提供任 API 的应用程序中使用它。
 
 | 何事务控制机制,因此不能在那 
 
 | 些需要并发访问从而不使用辅助 
 
 | 
 | Java 数据库连接(JDBC)是一个标 。诸如 JDBC 的调用级接口是编程接口,
 中的数据。通过提供与数据库连接的库例
 。特别是,JDBC 有一个使接口变得极其
 
 | 准的 API,它使用 Java 编程语言与数据库进行交互 它们允许从外部访问 SQL 命令来处理和更新数据库
 程,它们允许将 SQL 调用集成到通用的编程环境中
 简单和直观的例程的丰富收集。
 
 | 
 
 | 在下面几个小节中,我 关注与 Java 对象序列化相
 
 | 们将查看通过 JDBC 与数据库连 比,JDBC 是如何成为一个企业
 
 | 接所涉及的一些步骤。我们将特别 数据管理策略的。
 
 | 
 
 
 | 在利用 JDBC 做任何其 且将该库添加到类路径中。
 码来实现实际的连接。
 
 | 他事情之前,需要从驱动程序供 一旦完这项工作,就可以在 Jav
 
 
 | 应商那里获取数据库驱动程序,并 a 程序中使用类似于下面所示的代
 
 
 | 
 
 | Class.forName(<your driver class Name>); | 
 
 | Java.sql.Connection conn = DriverManager.getConnection(<connection URL>); | 
 
 
 | Java 对象序列化并不需要这个该步 DBMS。 序列化是一个基于文件的机制;
 中打开一个 I/O 流。
 
 | 骤,因为使用序列化来执行持久性操作并不需要 因此,在序列化一个对象之前,需要在目标文件系统
 
 
 | 
 
 | 创建 JDBC Statement 和 PreparedStatement | 
 
 | 可以用 JDBC Statemen 将该对象与 SQL 语句混淆
 的 SQL 语句有关联。可以
 多个(您请求执行的)SQL
 
 | t 对象将 SQL 语句发送到数据 。 JDBC Statement 对象是与打
 将 JDBC Statement 对象看作是
 语句传送给 DBMS。
 
 | 库管理系统(DBMS),并且不应该 开连接有关联,而不是与任何单独
 位于连接上的一个通道,将一个或
 
 
 | 
 
 | 为了创建 Statement 对象,您需要 Connection 对象 con——下面的代码来
 
 | 一个活动的连接。通过使用我们前面所创建的 完成这项工作。
 
 | 
 
 | Statement stmt = con.createState 
 | ment(); 
 | 
 
 | 到目前为止,我们已经 SQL 语句。
 
 | 有了一个 Statement 对象,但 
 
 | 是还没有将对象传递到 DBMS 的 
 
 | 
 
 | 当数据库接收到语句时 的分析,数据库就必须计算
 查哪些索引可以提供帮助,
 行。数据库针对数据进行统
 以执行它。
 
 | ,数据库引擎首先会分析该语句 出执行它的最有效方法。在计算
 如果存在这样的索引的话,或者
 计,找出最佳的执行方式。一旦
 
 
 | 并查找句法错误。一旦完成对语句 上,这可能非常昂贵。数据库会检
 检查是否应该完全读取表中的所有
 创建好查询计划,数据库引擎就可
 
 
 | 
 
 | 生成这样一个计划会占用 CPU 资源 库,那么我们希望数据库重用第一个语句
 象来获得这种效果。
 
 | 。理想情况是,如果我们两次发送相同的语句到数据 的访问计划,我们可以使用 PreparedStatement 对
 
 
 | 
 
 | 这里有一个主要的特性是,将 Prepa Statement 不同,在创建 PreparedState
 送给 DBMS,在那里编译该语句。因而,
 和被编译的 SQL 语句相关联的。
 
 | redStatement 与其超类 Statement 区别开来:与 ment 时,会提供一个 SQL 语句。然后了立即将它发
 PreparedStatement 实际上是作为一 个通道与连接
 
 
 | 
 
 | 那么,它的优势是什么 利用 PreparedStatement,
 Statement 相比,每次使用
 
 | 呢?如果需要多次使用相同的查 语句,只需被 DBMS 编译和优化
 相同的 SQL 语句都需要重新编
 
 | 询或者不同参数的类似查询,那么 一次即可。与使用正常的
 译一次。
 
 | 
 
 | 还可以通过 Connectio 有三个输入参数的参数化了
 
 | n 方法创建PreparedStatement 的 SQL 语句。
 
 | 。下面代码显示了如何创建一个带 
 
 | 
 | PreparedStatement 
 | prepareUpdatePrice = con.pr 
 | epareStatement( 
 | 
 | "UPDATE Sells 
 | SET price = ? WHERE bar = ? 
 | AND beer = ?"); 
 | 
 
 | 注意,Java 序列化不 惟一途径就是反序列化该对
 整的对象在计算上可能很昂
 
 | 支持类似于 SQL 的查询语言。 象,并调用该对象上的 getter/
 贵,尤其是在程序的生命期中,
 
 | 使用 Java 序列化访问对象属性的 accessor 方法。反序列化一个完
 应用程序需要重复执行它。
 
 | 
 
 | 在执行 PreparedStatement 之前, 中定义的 setXXX() 方法可以实现它。最
 setDouble(),以及 setString()。每次
 
 | 需要向参数提供值。通过调用 PreparedStatement 常使用的方法是 setInt(),setFloat(),
 执行已准备的声明之前,都需要设置这些值。
 
 | 
 
 
 | 执行 JDBC 中的 SQL 言)语句(例如表建立和表
 执行的。列表 2 中包含 ex
 
 | 语句的方式是根据 SQL 语句的 更改语句)和更新表内容的语句
 ecuteUpdate() 语句的实例。
 
 | 目的而变化的。DDL(数据定义语 都是通过使用 executeUpdate()
 
 
 | 
 
 | 列表 2. 实际运行中的 executeUpdate() | 
 
 | Statement stmt = 
 | con.createStatement(); 
 | 
 
 | stmt.executeUpdate("CREATE TA 
 | BLE Sells " + 
 | 
 | "(bar VARCHAR2 
 | (40), beer VARCHAR2(40), pri 
 | ce REAL)" ); 
 | 
 | stmt.executeUpdate("INSERT IN 
 | TO Sells " + 
 | 
 | "VALUES ('Bar 
 | Of Foo', 'BudLite', 2.00)" ) 
 | ; 
 | 
 
 | String sqlString 
 | = "CREATE TABLE Bars " + 
 | 
 | "(name VARCHAR2(40), addre 
 | ss VARCHAR2(80), license INT)" ; 
 | 
 | stmt.executeUpdate(sqlString); | 
 
 | 我们将通过先前插入的 用 executeUpdate(),如下
 
 | 参数值(如上所示)执行 Prepa 所示:
 
 | redStatement ,然后在这之上调 
 
 | 
 
 | int n = prepareUpdatePrice 
 | .executeUpdate() ; 
 | 
 
 | 相比之下,查询期望返回一个行作为 称为 executeQuery() 的相对应的方法,
 
 | 它的结果,并且并不改变数据库的状态。这里有一个 它的返回值是 ResultSet 对象,如列表 3 所示。
 
 | 
 
 
 
 | ResultSet rs = st 
 | mt.executeQuery("SELECT * FR 
 | OM Sells"); 
 | 
 | bar = rs.getString("bar"); | 
 | beer = rs.getString("beer"); | 
 | price = rs.getFloat("price"); | 
 | System.out.println(bar + " Dollars.");
 
 | sells " + beer + " for " + price + " 
 
 | 
 
 | 由于查询而产生的行集包含在变量 r 我们来说并没有太大用处,除非我们可以
 供了一个光标,可以用它依次访问每一个
 每个方法调用都会导致光标向下一行移动
 的行,则返回 false。
 
 | s 中,该变量是 ResultSet 的一个实例。集合对于 访问每一个行以及每一个行中的属性。ResultSet 提
 行。光标最初被设置在正好位于第一行之前的位置。
 ,如果该行存在,则返回 true,或者如果没有剩余
 
 
 | 
 
 | 我们可以使用适当类型的 getXXX() getString() 和 getFloat() 方法来访
 数的列的名称;我们可以指定用列号来代
 依次类推。
 
 | 来检索某一个行的属性。在前面的实例中,我们使用 问列值。注意,我们提供了其值被期望用作方法的参
 替列名。检索到的第一列的列号为 1,第二列为 2,
 
 
 | 
 
 | 在使用 PreparedStatement 时,可 executeQuery(),如下所示:
 
 | 以通过先前插入的参数值来执行查询,然后对它调用 
 
 | 
 
 | ResultSet rs = prepareUpda 
 | tePrice.executeQuery() ; 
 | 
 
 
 | JDBC 还提供一系列发 isBeforeFirst(),isLast(
 
 | 现您在结果集中的位置的方法: ),以及 isAfterLast()。
 
 | getRow(),isFirst(), 
 
 | 
 
 | 这里还有一些使可滚动 只向前滚动,并且是只读的
 型更改为更为灵活的可滚动
 
 | 光标能够自由访问结果集中的任 。在为 Connection 创建 State
 或可更新模型,如下所示:
 
 | 意行的方法。在默认情况下,光标 ment 时,可以将 ResultSet 的类
 
 
 | 
 
 | Statement stmt = con.creat ResultSet.CONCUR_READ_ONLY);
 
 | eStatement(ResultSet.TYPE_FORWARD_ONLY, 
 
 | 
 | ResultSet rs = stmt.execut 
 | eQuery("SELECT * FROM Sells"); 
 | 
 
 | 不同的类型选项: TYPE_FORWARD_ON TYPE_SCROLL_SENSITIVE 。可以通过使用
 择光标是只读的还是可更新的。对于默认
 动的光标,您有更多的选项,如下所示:
 
 | LY 、 TYPE_SCROLL_INSENSITIVE 和 CONCUR_READ_ONLY 和 CONCUR_UPDATABLE 选项来选
 光标,可以使用 rs.next() 向前滚动它。对于可滚
 
 
 | 
 
 | rs.absolute(3);     / 
 | / moves to the third retrieved row 
 | 
 | rs.previous(); set
 
 | // moves back one 
 
 | row in the retrieved result 
 
 | 
 | rs.relative(2);     / result set
 
 | / moves forward two rows in the retrieved 
 
 | 
 | rs.relative(-3);     / result set
 
 | / moves back three rows in the retrieved 
 
 | 
 
 | 对于可滚动光标的工作 是有用的,但是它导致极大
 找到关于可滚动 ResultSet
 
 | 方式,这里有更多的详细描述。 的性能损失,所以应该限制和谨
 的更多信息。
 
 | 尽管可滚动光标对于特定应用程序 慎使用。可以在 参考资料小节中
 
 
 | 
 
 | 在序列化中不存在与 JDBC 的 Resul 据的角度不同。JDBC (通常)假定底层
 对象图。两种技术的底层数据结构存在显
 化的对象图结构,反之亦然。当通过使用
 结构变成了一个字节流,该字节流展示了
 。
 
 | tSet 相对应的机制。序列化和 JDBC 观察底层的数 数据是关系型结构的;而序列化假定底层数据是一个
 著差异。JDBC 的 Set 结构并不能自然地映射到序列
 序列化语义将一个 Java 对象持久化时,数据的底层
 已经序列化了的核心对象的各种内部对象之间的关联
 
 
 | 
 
 | JDBC 中的 ResultSet 中,这是不可能的,因为序
 此,Java 对象序列化无法
 
 | 导航是从一个 Set 元素移动到 列化涉及到对象关联,而不是将
 向您提供用这种方式访问数据单
 
 | 其他元素的过程,而在对象序列化 一组行封装到一个实体集合中。因
 独某个部分的能力。
 
 | 
 
 
 | JDBC 允许将 SQL 语句组合到单独一 来确保 ACID 属性。
 
 | 个事务中。因此,我们可以通过使用 JDBC 事务特性 
 
 | 
 
 | Connection 对象执行事务控制。当 。这意味着每个 SQL 语句自身都被看作
 
 | 建立连接时,在默认情况下,连接是自动提交模式下 是一个事务,并且一完成执行就会被提交。
 
 | 
 
 
 | con.setAutoCommit(false) ; | 
 | con.setAutoCommit(true) ; | 
 
 | 一旦关闭了自动提交, SQL 语句(即,数据库将不
 rollback() 回滚事务,并
 
 | 除非通过调用 commit() 显式地 会被持久地更新)。在提交之前
 恢复最近的提交值(在尝试更新
 
 | 告诉它提交语句,否则无法提交 的任何时间,我们都可以调用
 之前)。
 
 | 
 
 | 我们还可以设置期望的事务隔离等级 TRANSACTION_READ_COMMITTED,这使得在
 在 Connection 接口中为隔离等级提供了
 。JDBC 允许我们发现数据库所设置的是
 getTransactionIsolation() 方法)以及
 setTransactionIsolation() 方法)。
 
 | 。例如,我们可以将设置事务隔离等级为 提交值之前,不允许对它进行访问。并且禁止脏读。
 五个这样的值。默认情况下,隔离等级是可序列化的
 什么事务隔离等级(使用 Connection 的
 设置适当的等级(使用 Connection 的
 
 
 | 
 
 | 回滚通常与 Java 语言的异常处理能 一个简单高效的机制。在下一节中,我们
 
 | 力结合在一起使用。这种结合为处理数据完整性提供 将研究如何使用 JDBC 进行错误处理。
 
 | 
 
 | 注意,Java 对象序列 其他的 API,例如 JTA,来
 一个更新操作时同步该序列
 
 | 化并不直接支持事务管理。如果 获得这个效果。然而,为了获得
 化对象,如下所示:
 
 | 您正在使用序列化,则将需要借助 事务隔离的效果,可以选择在执行
 
 
 | 
 
 | Synchronized(my_deserialized_o 
 | bject) { 
 | 
 | //Perform the updates etc... | 
 
 
 | 软件程序中总是出现一 处理错误是有必要的。程序
 常处理程序结合使用是达到
 
 | 些错误。通常,数据库程序是关 应该恢复并且让数据库处于某种
 这种要求的一种简便方法。
 
 | 键性应用程序,而且适当地捕获和 一致的状态下。将回滚与 Java 异
 
 
 | 
 
 | 访问服务器(数据库)的客户(程序 过提供两种等级的错误条件来访问这种信
 是 Java 异常,它(如果未被处理)将会
 子类,但是它们代表的是非致命错误或意
 
 | )需要能够识别从服务器返回的所有错误。JDBC 通 息:SQLException 和 SQLWarning。SQLException
 终止该应用程序。SQLWarning 是 SQLException 的
 想不到的条件,因此,可以忽略它们。
 
 | 
 
 | 在 Java 代码中,希望抛出异常或者 句抛出异常或者警告,那么可以在对应的
 它准备捕获的异常。
 
 | 警告的语句包含于 try 块中。如果在 try 块中的语 某个 catch 语句中捕获它。每个捕获语句都指出了
 
 
 | 
 
 | 换句话说,如果数据类 表,则可能会抛出一个异常
 SQLWarning。每个对象都
 行其他语句,则将放弃所有
 
 | 型是正确的,但是数据库大小超 。 可以从 Connection,Statem
 只是存储最近 SQLWarning。因
 早期的警告。列表 4 举例说明
 
 | 出其空间限制并且不能建立一个新 ent,以及 ResultSet 对象中获取
 此,如果通过 Statement 对象执
 了 SQLWarning 的使用。
 
 | 
 
 
 | ResultSet rs = 
 | stmt.executeQuery("SELECT b 
 | ar FROM Sells") ; 
 | 
 | SQLWarning war 
 | n = stmt.getWarnings() ; 
 | 
 | System.out.println("Mes 
 | sage: " + warn.getMessage()) ; 
 | 
 | SQLWarning warning = rs.ge 
 | tWarnings() ; 
 | 
 | warning = w 
 | arning.getNextWarning() ; 
 | 
 | System.out. 
 | println("Message: " + warn.g 
 | etMessage()) ; 
 | 
 
 | 实际上,SQLWarning DataTruncation 警告,它
 
 | 在某种程度上比 SQLException 表示在从数据库读或写数据时存
 
 | 更为罕见。最常见的是 在问题。
 
 | 
 
 | Java 并没有提供序列 行的 I/O 操作有关,因此
 
 | 化所使用的特定的异常类。使用 ,在这些情况中 I/O 异常类将
 
 | 序列化时发生的大多数异常都与执 满足要求。
 
 | 
 
 
 | JDBC 2.0 提供一个用于批处理的强 一起发送并处理。一个典型的批处理就是
 账号。在减少从 Java 代码到数据库的往
 
 | 大API。批处理允许积累一组 SQL 语句,并且将它们 银行应用程序,该应用程序每隔一刻钟就要更新许多
 返次数方面,批处理是一个强大功能。
 
 | 
 
 | Statement 接口提供 a 已经将所有的 SQL 语句都
 们。
 
 | ddBatch(String) 方法,将 SQL 增加到该批处理中,就可以使用
 
 
 | 语句添加到一个批处理中。一旦 executeBatch() 方法一起执行它
 
 
 | 
 
 | 然后,用executeBatch 受每条语句影响的行数。将
 理中会导致 SQLException
 
 | () 方法执行 SQL 语句,并返回 SELECT 语句或者其他返回 Res
 。
 
 | int 值的一个数组。该数组包含 ultSet 的 SQL 语句放在一个批处
 
 
 | 
 
 | 列表 5 中列出了利用 java.sql.Sta 
 | tement 进行批处理的一个简单实例。 
 | 
 
 
 | Statement stmt = con 
 | n.createStatement(); 
 | 
 | stmt.insert("DELETE FROM Users"); | 
 | stmt.insert("INSERT 
 | INTO Users VALUES('rod', 37, 
 | 'circle')"); 
 | 
 | stmt.insert("INSERT 
 | INTO Users VALUES('jane', 33 
 | , 'triangle')"); 
 | 
 | stmt.insert("INSERT INTO Users V 
 | ALUES('freddy', 29, 'square')"); 
 | 
 | int[] counts = stmt.executeBatch(); | 
 
 | 在您不知道特定语句将运行的次数时 果在不使用批处理的情况下试图插入 100
 脚本,增加 10000 条记录,那么情况会
 能够提高代码的可读性。
 
 | ,批处理是一个处理 SQL 代码的好方法。例如,如 条记录,那么性能可能会受到影响。如果编写一个
 变得更糟。添加批处理可以帮助提高性能,后者甚至
 
 
 | 
 
 | Java 对象序列化并不支持批处理。 ,在这种情况下,批处理没有意义。因此
 的灵活性,而这些对于序列化来说不一定
 
 | 通常,会在某个对象的范围(联系图)上运用序列化 ,批处理在数据更新的定时和分组方面为您提供一定
 是可用的。
 
 | 
 
 
 | 存储过程是一组 SQL 语句,它们建 程来封装一个操作或者查询的集合,这些
 程是在数据库服务器中被编译和存储的。
 的二进制代码,因此执行速度会更快。
 
 | 立了一个逻辑单元,并执行特定任务。可以用存储过 操作或查询都将在一个数据库服务器上执行。存储过
 因此,每次调用存储过程时,DBMS 都将重用已编译
 
 
 | 
 
 | JDBC 允许您从 Java 应用程序中调 CallableStatement 对象。与 Statement
 个打开的 Connection 对象完成的。Call
 不包含存储过程自身。列表 6 中的第一
 SHOW_ACCOUNT 的调用。波形括号中括住
 {call SHOW_ACCOUNT} 时,它将该转义语
 SHOW_ACCOUNT 的存储过程。
 
 | 用数据库存储过程。第一步是创建 和 PreparedStatement 对象一样,这项操作是用一
 ableStatement 对象包含对存储过程的调用;但它并
 行代码使用 con 连接建立了对存储过程
 的部分是存储过程的转义语法。当驱动程序遇到
 法翻译成数据库所使用的本地 SQL,从而调用名为
 
 
 | 
 
 | CallableStatement cs = con.prepa 
 | reCall("{call SHOW_ACCOUNT(?)}"); 
 | 
 | cs.setInt(1,myaccountnumber); | 
 | ResultSet rs = cs.executeQuery(); | 
 
 | 假设 Sybase 中的存储 
 | 过程 SHOW_ACCOUNT 包含列表 7 
 | 中所示的代码。 
 | 
 
 | Listing 7. SHOW_ACCOUNT stored p 
 | rocedure 
 | 
 | CREATE PROCEDURE SHOW_ACCOUNT (@ 
 | Acc int) 
 | 
 | Select balance from USER_ACCOUN 
 | TS where Account_no = @Acc 
 | 
 
 
 
 | 注意,用来执行 cs 的方法是 execu 询,所以只产生一个结果集。如果该过程
 executeUpdate() 方法。然而,有时候存
 下,它将产生多个结果集、多个更新计数
 用 execute() 方法执行 CallableStatem
 
 | teQuery(),由于 cs 调用的存储过程只包含一个查 只包含一个更新或者一个 DDL 语句,则将使用
 在存储过程包含多个 SQL 语句的情况,在这种情况
 ,或者结果集和更新计数的某种结合。因此,应该使
 ent。
 
 | 
 
 | CallableStatement 类是 PreparedS 以接受与 PreparedStatement 对象相同
 出参数,并将该参数用于输入和输出。IN
 理 OUT 参数,需要通过使用 registerOu
 过程。
 
 | tatement 的子类,因此 CallableStatement 对象可 的参数。而且,CallableStatement 对象可以接受输
 OUT 参数和 execute() 方法通常很少使用。要想处
 tParameter(int, int) 方法将 OUT 参数注册到存储
 
 
 | 
 
 | 举例说明,我们假设 GET_ACCOUNT 过程包含列表 8 中的代码。 | 
 
 
 | CREATE PROCEDURE GET_ACCOUNT (@A 
 | cc int, @balance float OUTPUT) 
 | 
 | Select @balance = balance from U 
 | SER_ACCOUNTS where Account_no = @Acc 
 | 
 
 | 在这个实例中,参数 b 如列表 9 所示。
 
 | alance 被声明是一个 OUT 参数 
 
 | 。现在,调用该过程的 JDBC 代码 
 
 | 
 
 
 | CallableStatement cs 
 | mt = con.prepareCall("{GET_A 
 | CCOUNT(?,?)"); 
 | 
 | csmt.setInt(1,youraccountnumber); | 
 | csmt.registerOutParamter(2,java. 
 | sql.Types.FLOAT); 
 | 
 
 | 正使用 Java 序列化时 一个纯 Java 语言现象,它
 在与 CallableStatement
 者组件中,尽管这些系统或
 
 | ,并不需要访问任何外部的系统 不涉及执行一个外部环境中的已
 对象相对应的机制。这意味着您
 者组件可能更适合它。
 
 | ,如 DBMS。换句话说,序列化是 编译代码。因此,在序列化中不存
 不能将数据处理转移到外部系统或
 
 
 | 
 
 
 | 在读完本文之后,我们 序列化要好得多的方法。
 
 | 希望您赞同:对于数据管理和持 
 
 | 久化而言, JDBC 是比 Java 对象 
 
 | 
 
 | JDBC 是一个用来访问 集合来访问多种数据源。用
 源可以是关系型的、层次型
 接到目标数据源。JDBC 做
 将程序员从供应商特定的桎
 
 | 数据存储的极好的 API。 JDBC 户只需要学习一个 API 集合,
 的或者任何其他格式。您需要的
 了大量工作,将所有技术细节都
 梏中解放出来。
 
 | 最好的东西是它提供单一的 API 就可以访问任何数据源,这些数据
 只是一个 JDBC 驱动程序,用它连
 封装到了一个实现软件包中,从而
 
 
 | 
 
 | 表 1 对比了 JDBC 和 Java 对象序列化的各种特性。 | 
 
 
 | Java 对象序列化和 JDBC 是 Java 多个 JVM 之间以 Java 语言特定格式共
 ,序列化最适合不过。然而,Java 序列
 对这些数据进行组织。在这样的企业系统
 系统并不一定都与 Java 语言兼容。在这
 
 | 技术领域中许多数据持久化机制中的两种。在需要在 享数据(例如用 RMI 的按值传递机制共享数据)时
 化并不适用于企业数据,需要以一种定义良好的结构
 中,需要在多个系统和子系统之间共享数据,而这些
 种情况中,对象序列化根本不能工作。
 
 | 
 
 | JDBC 提供一个公用 API来访问异构 。它提供了一个使用 Java 平台访问数据
 CRUD 操作所需的所有代码都是由开发人
 
 | 的数据存储。它是 JVM 和目标 DBMS 之间的粘合剂 存储和维护企业数据的纲领性方法。然而,执行
 员编写。
 
 | 
 
 | 为了在企业环境中最有 一个用于数据持久性的框架
 关,因此强烈建议将数据持
 常有帮助。
 
 | 效地使用 JDBC,架构设计人员 。由于使用 JDBC 持久化数据的
 久性层与应用程序的商业逻辑相
 
 
 | 需要分析其企业中的数据,并开发 机制与系统想要解决的商业问题无
 分离。设计模式对设计这种框架非
 | 
 |  |  |  |