帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程
J2EE 应用程序中的数据管理和数据持久性
作者:佚名 发布时间:2005-04-02 来源:不详
 
 本文分析了在 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 持久性策略。对象序列化
是作为对象继承、关联和聚合的
式被写入到持久存储中。实例属
象是可序列化的,那么它至少必
结构:
是一个将对象图平面化为一个字节
结果而实现的一些关系式。对象的
性的值就是执行时间序列化时内存
须实现 java.io.Serializable 接


  package java.io;                                              
  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()                      
  {                                                                            
   return property1;                                          
  }                                                                            

  public void setProperty1(String val)      
  {                                                                            
   property1 = val;                                            
  }                                                                            
  public String getProperty2()                      
  {                                                                            
   return property2;                                          
  }                                                                            

  public void setProperty2(String val)      
  {                                                                            
     property2 = val;                                        
  }                                                                            
     private void w
riteObject(ObjectOutputStrea
m out)
     throws IOException                                    
     {                                                                      
      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()方
化实例,并且共享对该对象引用的
独立于其他对象可能维护的任何引
被序列化,从而获得一个类似于对


  Java 对象序列化存在的问题

  序列化涉及到将对象图
销。通常,对应用程序而言
从内存具体化到持久存储(例如
,序列化并不是最佳选择:
硬盘)中。这涉及到大量 I/O 开


  管理几十万兆字节的存储数据                                                   
  频繁地更新可序列化对象                                                       
  对存储企业数据而言,序列化是一个错误选择,因为:                              

  序列化的字节流只对 Java 语言是可
的,许多应用程序要与其他应用程序共同
读的。这是一个重大缺陷,因为企业系统通常是异构
处理相同的数据。

  对象检索涉及大量的 I/O 开销。                                            

  没有一个用来从序列化对象图中检索获取数据的查询语言。                          

  序列化没有内置的安全机制。                                                    

  序列化本身并不提供任
API 的应用程序中使用它。
何事务控制机制,因此不能在那

些需要并发访问从而不使用辅助

  Java 数据库连接(JDBC)                                              
  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 所示。

  列表 3. 执行一个查询                                                      

    String bar, beer ;                                      
    float price ;                                                

    ResultSet rs = st
mt.executeQuery("SELECT * FR
OM Sells");
    while ( rs.next() ) {                                
     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() ;

  关于访问 ResultSet 的注释

  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 的使用。

  列表 4. 实际运行中的 SQLWarnings                              

     ResultSet rs =
stmt.executeQuery("SELECT b
ar FROM Sells") ;

     SQLWarning war
n = stmt.getWarnings() ;
     if (warn != null)                                      
       System.out.println("Mes
sage: " + warn.getMessage()) ;
     SQLWarning warning = rs.ge
tWarnings() ;
     if (warning != null)                                

       warning = w
arning.getNextWarning() ;
     if (warning != null)                                
       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 进行批处理的一个简单实例。

  列表 5. 实际运行中的批处理                                                


  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 对象序列化并不支持批处理。
,在这种情况下,批处理没有意义。因此
的灵活性,而这些对于序列化来说不一定
通常,会在某个对象的范围(联系图)上运用序列化
,批处理在数据更新的定时和分组方面为您提供一定
是可用的。

  从 Java 代码调用存储过程

  存储过程是一组 SQL 语句,它们建
程来封装一个操作或者查询的集合,这些
程是在数据库服务器中被编译和存储的。
的二进制代码,因此执行速度会更快。
立了一个逻辑单元,并执行特定任务。可以用存储过
操作或查询都将在一个数据库服务器上执行。存储过
因此,每次调用存储过程时,DBMS 都将重用已编译


  JDBC 允许您从 Java 应用程序中调
CallableStatement 对象。与 Statement
个打开的 Connection 对象完成的。Call
不包含存储过程自身。列表 6 中的第一
SHOW_ACCOUNT 的调用。波形括号中括住
{call SHOW_ACCOUNT} 时,它将该转义语
SHOW_ACCOUNT 的存储过程。
用数据库存储过程。第一步是创建
和 PreparedStatement 对象一样,这项操作是用一
ableStatement 对象包含对存储过程的调用;但它并
行代码使用 con 连接建立了对存储过程
的部分是存储过程的转义语法。当驱动程序遇到
法翻译成数据库所使用的本地 SQL,从而调用名为


  列表 6. 实际运行中的存储过程                                              
                                                                               
  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)
  AS                                                                          
  BEGIN                                                                    
   Select balance from USER_ACCOUN
TS where Account_no = @Acc
  END                                                                        

  ResultSet rs 看起来类似于:                                      

  balance                                                           
  ----------------                                           
  12000.95                                                              

  注意,用来执行 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 中的代码。      

  列表 8. GET_ACCOUNT                                           

  CREATE PROCEDURE GET_ACCOUNT (@A
cc int, @balance float OUTPUT)
  AS                                                                          
  BEGIN                                                                    
  Select @balance = balance from U
SER_ACCOUNTS where Account_no = @Acc
  END                                                                        

  在这个实例中,参数 b
如列表 9 所示。
alance 被声明是一个 OUT 参数

。现在,调用该过程的 JDBC 代码


  列表 9. 调用一个存储过程的 JDBC 代码                                

  CallableStatement cs
mt = con.prepareCall("{GET_A
CCOUNT(?,?)");
  csmt.setInt(1,youraccountnumber);            
  csmt.registerOutParamter(2,java.
sql.Types.FLOAT);
  csmt.execute();                                                

  正使用 Java 序列化时
一个纯 Java 语言现象,它
在与 CallableStatement
者组件中,尽管这些系统或
,并不需要访问任何外部的系统
不涉及执行一个外部环境中的已
对象相对应的机制。这意味着您
者组件可能更适合它。
,如 DBMS。换句话说,序列化是
编译代码。因此,在序列化中不存
不能将数据处理转移到外部系统或


  包装

  在读完本文之后,我们
序列化要好得多的方法。
希望您赞同:对于数据管理和持

久化而言, JDBC 是比 Java 对象


  JDBC 是一个用来访问
集合来访问多种数据源。用
源可以是关系型的、层次型
接到目标数据源。JDBC 做
将程序员从供应商特定的桎
数据存储的极好的 API。 JDBC
户只需要学习一个 API 集合,
的或者任何其他格式。您需要的
了大量工作,将所有技术细节都
梏中解放出来。
最好的东西是它提供单一的 API
就可以访问任何数据源,这些数据
只是一个 JDBC 驱动程序,用它连
封装到了一个实现软件包中,从而


  表 1 对比了 JDBC 和 Java 对象序列化的各种特性。                

  表 1. JDBC 对 Java 序列化                                      
  

  Java 对象序列化和 JDBC 是 Java
多个 JVM 之间以 Java 语言特定格式共
,序列化最适合不过。然而,Java 序列
对这些数据进行组织。在这样的企业系统
系统并不一定都与 Java 语言兼容。在这
技术领域中许多数据持久化机制中的两种。在需要在
享数据(例如用 RMI 的按值传递机制共享数据)时
化并不适用于企业数据,需要以一种定义良好的结构
中,需要在多个系统和子系统之间共享数据,而这些
种情况中,对象序列化根本不能工作。

  JDBC 提供一个公用 API来访问异构
。它提供了一个使用 Java 平台访问数据
CRUD 操作所需的所有代码都是由开发人
的数据存储。它是 JVM 和目标 DBMS 之间的粘合剂
存储和维护企业数据的纲领性方法。然而,执行
员编写。

  为了在企业环境中最有
一个用于数据持久性的框架
关,因此强烈建议将数据持
常有帮助。
效地使用 JDBC,架构设计人员
。由于使用 JDBC 持久化数据的
久性层与应用程序的商业逻辑相

需要分析其企业中的数据,并开发
机制与系统想要解决的商业问题无
分离。设计模式对设计这种框架非
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·结合struts和hibernate谈J2EE架构  (2005-04-02)
 ·理解类加载器:J2EE 环境下的 lo  (2005-04-02)
 ·移动技术促进人和网络互动:.NET  (2005-04-02)
 ·J2EE 应用程序开发:专业设计师的  (2005-04-02)
 ·.NET和J2EE架构之战 正在升级  (2005-04-02)
 ·将J2EE平台提升到一个新的高度  (2005-04-02)
 ·J2EE Design Patterns  (2005-04-02)
 ·如何实现一个与数据库表字段松耦  (2005-04-02)
 ·solaris上开发J2EE应用中文问题的  (2005-04-02)
 ·J2EE应用系统内部的Web Services  (2005-04-02)

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·DiscuzX2.5会员整合通行证发布
·帝国CMS 7.0版本功能建议收集
·帝国网站管理系统2012年授权购买说
·PHPWind8.7会员整合通行证发布
·[官方插件]帝国CMS-访问统计插件
·[官方插件]帝国CMS-sitemap插件
·[官方插件]帝国CMS内容页评论AJAX分
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统