服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

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

扫描关注微信公众号