当前位置导航:炫浪网>>网络学院>>编程开发>>JAVA教程>>J2EE

J2EE 应用程序中的数据管理和数据持久性


  本文分析了在 Java 平台上可用的两个数据管理策略:Java 对象序列化和 Java 数据库连接(JDBC)。尽管本质上这两种数据管理策略并不存在孰优孰劣的问题,但在管理企业信息系统时,JDBC 轻而易举地得以胜出。在本文中,Java 开发人员 G.V.B. Subrahmanyam 和 Shankar Itchapurapu 对序列化和 JDBC都进行了介绍,并通过讨论和实例来向您展示了 JDBC 是您的最佳选择的原因。
  
  当您正在建立企业信息系统时,需要确保以某种有效的方式存储、检索和显示企业数据。对于所有业务而言,数据都是独一无二的最大资产。所有软件系统都涉及数据,因此,数据的重要性是无论如何强调都不过分的。
  
  应用程序的数据管理功能包括四个基本操作,通常也需要对企业数据执行这四个操作,它们是:建立、检索、更新 和 删除(即 CRUD)。管理在企业系统的数据涉及在很长一段时间范围之内,始终如一地、成功地执行 CRUD 操作,而不必频繁地更改实际执行这些操作的代码。换句话说,管理数据意味着开发稳健的、可扩展和可维护的软件系统,以确保成功地进行 CRUD 操作,在软件的生命期中能够以一致的方式执行操作。
  
  本文讨论了 J2EE 中的两种可用数据管理策略:Java 对象序列化和 Java 数据库连接(JDBC)。我们将查看这两种方法的优缺点。这两种数据管理策略实质上不存在孰优孰劣。在特定实现中,策略的可用性取决于项目的范围(出现在系统环境中的活动的活动范围),系统的上下文(驱动系统/子系统运行时的值的集合),以及其他的外部因素。然而,Java 序列化并不适合于企业系统,其数据需要用一种定义良好的结构(如RDBMS)来组织。我们首先将快速浏览 Java 对象序列化,然后查看 JDBC 更重要的一些方面,从而了解后者是如何实现前者所缺乏的一些关键特性的。
  
  本文并不打算对 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 MySerializableObject extends MySuperClass 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 writeObject(ObjectOutputStream out)
   throws IOException
   {
    out.writeObject (getProperty1 ());
   out.writeObject (getProperty2 ());
   }
  
   private void readObject (ObjectInputStream in)
   throws IOException, ClassNotFoundException
   {
    setProperty1 ((String) in.readObject ());
    setProperty2 ((String) in.readObject ());
   }
  }
  
  无需自己实现 writeObject(...) 和 readObject(...) 方法来执行序列化;Java 运行时环境具有使这些方法可用的默认实现。然而,您可以重写这些方法,提供如何存储对象状态的您自己的实现。
  
  关于序列化,您需要记住一些要点。首先,在序列化期间,整个对象图(即,所有父类和被引用类)都将被序列化。其次, Serializable 类的所有实例变量自身都应该是可序列化的,除非已经特别声明它们为暂态,或者已经重写 writeObject(...) 和 readObject(...) 来只序列化那些可序列化的实例变量。如果违反了后一规则,在运行时将出现一个异常。
  
  每个后续 J2SE 版本都对对象序列化系统进行少量的增加。J2SE 1.4 也相应地向 ObjectOutputStream and ObjectInputStream 增加 writeUnshared() and readUnshared()方法。通常,一个序列化的流只包含任何给定对象的一个序列化实例,并且共享对该对象引用的其他对象可以对它进行后向引用。通常期望序列化一个对象独立于其他对象可能维护的任何引用。非共享的读写方法允许对象作为新的、独一无二的对象被序列化,从而获得一个类似于对象克隆但开销更少的效果。
  
  Java 对象序列化存在的问题
  序列化涉及到将对象图从内存具体化到持久存储(例如硬盘)中。这涉及到大量 I/O 开销。通常,对应用程序而言,序列化并不是最佳选择:
  
  管理几十万兆字节的存储数据
  频繁地更新可序列化对象
  对存储企业数据而言,序列化是一个错误选择,因为:
  
  序列化的字节流只对 Java 语言是可读的。这是一个重大缺陷,因为企业系统通常是异构的,许多应用程序要与其他应用程序共同处理相同的数据。
  
  对象检索涉及大量的 I/O 开销。
  
  没有一个用来从序列化对象图中检索获取数据的查询语言。
  
  序列化没有内置的安全机制。
  
  序列化本身并不提供任何事务控制机制,因此不能在那些需要并发访问从而不使用辅助 API 的应用程序中使用它。
  Java 数据库连接(JDBC)
  Java 数据库连接(JDBC)是一个标准的 API,它使用 Java 编程语言与数据库进行交互。诸如 JDBC 的调用级接口是编程接口,它们允许从外部访问 SQL 命令来处理和更新数据库中的数据。通过提供与数据库连接的库例程,它们允许将 SQL 调用集成到通用的编程环境中。特别是,JDBC 有一个使接口变得极其简单和直观的例程的丰富收集。
  
  在下面几个小节中,我们将查看通过 JDBC 与数据库连接所涉及的一些步骤。我们将特别关注与 Java 对象序列化相比,JDBC 是如何成为一个企业数据管理策略的。
  
  建立一个数据库连接
  在利用 JDBC 做任何其他事情之前,需要从驱动程序供应商那里获取数据库驱动程序,并且将该库添加到类路径中。一旦完这项工作,就可以在 Java 程序中使用类似于下面所示的代码来实现实际的连接。
  
  Class.forName(<your driver class Name>);
  Java.sql.Connection conn = DriverManager.getConnection(<connection URL>);
  
  Java 对象序列化并不需要这个该步骤,因为使用序列化来执行持久性操作并不需要 DBMS。 序列化是一个基于文件的机制;因此,在序列化一个对象之前,需要在目标文件系统中打开一个 I/O 流。
  
  创建 JDBC Statement 和 PreparedStatement
  可以用 JDBC Statement 对象将 SQL 语句发送到数据库管理系统(DBMS),并且不应该将该对象与 SQL 语句混淆。 JDBC Statement 对象是与打开连接有关联,而不是与任何单独的 SQL 语句有关联。可以将 JDBC Statement 对象看作是位于连接上的一个通道,将一个或多个(您请求执行的)SQL 语句传送给 DBMS。
  
  为了创建 Statement 对象,您需要一个活动的连接。通过使用我们前面所创建的 Connection 对象 con——下面的代码来完成这项工作。
  
  Statement stmt = con.createStatement();
  
  到目前为止,我们已经有了一个 Statement 对象,但是还没有将对象传递到 DBMS 的 SQL 语句。
  
  当数据库接收到语句时,数据库引擎首先会分析该语句并查找句法错误。一旦完成对语句的分析,数据库就必须计算出执行它的最有效方法。在计算上,这可能非常昂贵。数据库会检查哪些索引可以提供帮助,如果存在这样的索引的话,或者检查是否应该完全读取表中的所有行。数据库针对数据进行统计,找出最佳的执行方式。一旦创建好查询计划,数据库引擎就可以执行它。
  
  生成这样一个计划会占用 CPU 资源。理想情况是,如果我们两次发送相同的语句到数据库,那么我们希望数据库重用第一个语句的访问计划,我们可以使用 PreparedStatement 对象来获得这种效果。
  
  这里有一个主要的特性是,将 PreparedStatement 与其超类 Statement 区别开来:与 Statement 不同,在创建 PreparedStatement 时,会提供一个 SQL 语句。然后了立即将它发送给 DBMS,在那里编译该语句。因而, PreparedStatement 实际上是作为一 个通道与连接和被编译的 SQL 语句相关联的。
  
  那么,它的优势是什么呢?如果需要多次使用相同的查询或者不同参数的类似查询,那么利用 PreparedStatement,语句,只需被 DBMS 编译和优化一次即可。与使用正常的 Statement 相比,每次使用相同的 SQL 语句都需要重新编译一次。
  
  还可以通过 Connection 方法创建PreparedStatement 。下面代码显示了如何创建一个带有三个输入参数的参数化了的 SQL 语句。
  
  Prepa
相关内容
赞助商链接