您的位置:首页 > 编程语言 > Java开发

[转]使用WebRowSet完成JDBC的大部分任务

2008-04-29 10:51 465 查看

摘要:

    在这篇文章中,我首先将简要解释它的继承层次结构,紧接着,我会使用一个例子演示如何利用javax.sql.rowset.WebRowSet接口的特征非常容易地将数据库中的数据转化为XML文件,或者相反操作。然后我会讨论这个接口的利弊。在以上解释的基础上,我会总结一些首选这个接口的情况。

    任何现实世界中的企业级应用都需要访问持久化存储。关系型数据库管理系统(RDBMS)是使用最广泛的持久化存储机制,它支持使用SQL进行数据查询和更新。JDBC(Java DataBase Connectivity)是一系列的API,这些API为Java程序提供了一个使用SQL查询和更新RDBMS的框架。

    通过Java程序从数据库中获取数据或者更新数据库的过程包含了多个步骤。首先,程序需要建立一个连接,它可以和目标数据库进行通信。我们可以通过几种不同的方法建立数据库连接。传统的方式是,Java程序在装载了制造商提供的JDBC驱动后,调用java.sql.DriverManager类中适当的getConnection()方法获得连接。另外一个(也是首选的)方式是,使用制造商提供的实现或者编写一个针对目标数据库的实现了javax.sql.Connection接口的自定义类进行连接对象的初始化。在更多的受约束环境中,例如Java EE容器,提供了使用JNDI(Java Naming and Directory Interface)查找获得数据库连接的方式。无论程序使用哪一种方式建立数据库连接,如果连接成功,它应该有一个对java.sql.Connection接口实例的引用。通过连接,程序创建一个java.sql.Statement实例,或者一个包含数据库查询的子接口。最后,程序执行这个语句,获得一个java.sql.ResultSet实例,它表示从数据库中获得的满足查询的实际数据。

    在写这篇文章时,JDK5.0是支持JDBC3.0的Java最新版本。JDBC3.0提供了一些特征,增加了数据操作和转换的易用性和适应性。

    在这篇文章中,我首先将简要解释它的继承层次结构,紧接着,我会使用一个例子演示如何利用javax.sql.rowset.WebRowSet接口的特征非常容易地将数据库中的数据转化为XML文件,或者相反操作。然后我会讨论这个接口的利弊。在以上解释的基础上,我会总结一些首选这个接口的情况。

版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:Sharad Acharya;mydeman
原文:http://www.onjava.com/pub/a/onjava/2006/06/21/making-most-of-jdbc-with-webrowset.html
Matrix:http://www.matrix.org.cn/resource/article/44/44626_WebRowSet.html
关键字:WebRowSet;JDBC

WebRowSet层次结构

    我们开始先对WebRowSet接口的继承层次结构作一个简要的解释。图1显示了相关的Java元素(包、接口和类),它们也是讨论的一部分。



图1 WebRowSet的继承层次结构

    继承层次结构的根部是java.sql.ResultSet接口。这个接口的实例代表表格式的数据,这些数据通过执行包含对底层数据库查询的java.sql.Statement获取。默认的结果集只能前向遍历,并且不能更新。你不可能通过遍历默认结果集的方式进行精确的控制。
    那么,你有哪些选择呢?这就依赖于你要对结果集进行什么操作。例如,如果你想结果集支持适合于JavaBeans组件模型的JDBC API,就需要使用java.sql.ResultSet的子接口javax.sql.RowSet。

    因为Java程序访问数据库是一个重量级操作,所以内存中的数据高速缓存就是一个关系应用程序性能的关键因素。如果你想结果集作为一个行数据的容器缓存在内存中,那么你可以使用javax.sql.rowset.CachedRowSet,它是javax.sql.RowSet的子接口。这个接口的实例提供了不用一直保持连接数据源而操作数据的能力。更进一步,它是可滚动、可更新和可序列化的。除数据库以外,它可以对其它表格式结构的数据源起作用,如电子数据表。

    如果除了迄今为止提到的所有特征,你还要将结果集输出到XML和使用有效的XML作为输入,请选择javax.sql.rowset.WebRowSet.。在Sun的参考实现类中已经提供了它的实例的一个实现,com.sun.rowset.WebRowSetImpl,并作为JDK5.0的一部分发行。

    在层次结构的底部是javax.sql.rowset.JoinRowSet,javax.sql.rowset.WebRowSet的子接口,它提供了联合多个相关结果集对象的方式,就像对底层数据库表构造的SQL JOIN。

使用简单结果集

    伴随上面的介绍给你留下的印象,我向你展示一个简单的例子。这篇文章的所有例子开发环境都是Eclipse3.1.0,JDK5.0、Windows XP上的Oracle10.2。示例代码和输出文件参见资源部分。
我们考虑一个简单的student表,它定义了四列来存储信息。接下来的表格显示了查询该表获得的结果。
SQL>select * from student;

ID        FNAME        LNAME        AGE
200        Jack        Dakota        21
100        John        Doe        26

首先,我们编写一个Java类,它连接到包含student表的数据库,并且获取它的纪录。

public class DatasourceConnector {
public static void main(String[] args) {
   Connection con =null;
   DataSource ds =null;
   try {
     ds = new OracleDataSource();
       ds.setUser("<dbuser>");
       ds.setPassword("<password>");
       ds.setURL(
       "jdbc:oracle:thin:@localhost:1521:<sid>");
     } catch (SQLException e) {
       e.printStackTrace();
   }
   try {
     con = ds.getConnection();
     Statement stmt = con.createStatement();
     ResultSet rs =
       stmt.executeQuery(
         "select * from student ");     for (int j=0;
           j<rs.getMetaData().getColumnCount();
           j++)
         {
       System.out.print(
         rs.getMetaData().
           getColumnName(j+1)+"/t");
     }
     while (rs.next()) {
       System.out.print("/n");
           for (int i=0;
             i< rs.getMetaData().getColumnCount();
             i++)
           {
         System.out.print(
           rs.getString(i+1)+"/t");
        }
     }
     rs.close();
     stmt.close();
     con.close();
   } catch (SQLException e) {
   e.printStackTrace();
   }
  }
}


    例中的Java类初始化了一个连接对象,创建了一个包含查询字符串的语句(statement),最后获取结果。你需要提供数据库的用户ID、密码以及数据库的SID,在程序中都使用“<…>”标志。保存这个文件为DatasourceConnector.java,编译、运行:
>javac DatasourceConnector.java
>java DatasourceConnector

    应该一切正常,你应该可以看到类似下面的结果:

ID FNAME LNAME AGE
200 Jack Dakota 21
100 John Doe 26


导出结果集

    现在我把这个例子更进一步,假定这个程序是一个应用的一部分,应用要求数据从数据库转化为XML以进行更进一步地处理。我将使用实现类com.sun.rowset.WebRowSetImpl来完成这个任务。为了实际看到这个结果,我加入一些代码构造一个javax.sql.rowset.WebRowSet的实例,并且导出结果集到XML文件。如下所示:

... ... ...
ResultSet rs =
  stmt.executeQuery("select * from student");
WebRowSet wrs = new WebRowSetImpl();
wrs.populate(rs);
try {
  wrs.writeXml(
  new FileOutputStream("student.xml"));
} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}
... ... ...


    从wrs.writeXML()输出的结果形成一个符合WebRowSet schema定义的XML文档。它包含了三部分:属性、元数据和数据。大致的布局如下所示,完整的输出文件参见资源部分。

<?xml version="1.0"?>
<webRowSet xmlns=
"http://java.sun.com/xml/ns/jdbc"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrowset.xsd"> < properties>
... ... ...
</properties>
<metadata>
       ... ... ...
</metadata>
<data>
... ... ...
</data>
</webRowSet>


    <properties>标签提供了同步提供者的细节,例如隔离级别(isolation level)、RowSet类型等等。<metadata>标签提供了底层数据库表的信息,例如纪录数、名称和列的类型等等。<data>标签包含了实际数据,上面的表如下所示:

<data>
   <currentRow>
     <columnValue>200 < /columnValue>
     <columnValue>Jack</columnValue>
     <columnValue>Dakota</columnValue>
     <columnValue>21</columnValue>
   </currentRow>
   <currentRow>
     <columnValue>100</columnValue>
     <columnValue>John</columnValue>
     <columnValue>Doe</columnValue>
     <columnValue>26</columnValue>
   </currentRow>
</data>


    上例中的<currentRow>标签显示了WebRowSet对象值,当前可以不用任何更改地映射到底层数据源中。任何数据处理操作如插入、更新或删除都可以在输出的XML中被恰当的标记出来,我将会在接下来的部分解释。

 
操作结果集

    你可以删除一行数据,先移动指针到这一行的位置上,然后调用WebRowSet实例的deleteRow()方法。同样,你可以更新一个或者多个值,先移动指针到这个行的位置,然后调用合适的更新方法。下面的代码同时完成了删除和更新:

... ... ...
ResultSet rs =
  stmt.executeQuery("select * from student ");
WebRowSet wrs = new WebRowSetImpl();
wrs.populate(rs);
wrs.absolute(1); //move to first row
wrs.deleteRow(); //delete current row
wrs.absolute(2); //move to second row
wrs.updateInt(4,20);//update current row
... ... ...


    前四行代码片断的作用是很明显的:初始化对象并且转化结果集。接下来的两行尝试删除第一行。最后两行试图把第二行纪录的第四列的值更新为20。输出这个WebRowSet对象会产生如下的<data>元素:

<data>
   <deleteRow>
     <columnValue>200</columnValue>
     <columnValue>Jack</columnValue>
     <columnValue>Dakota</columnValue>
     <columnValue>21</columnValue>
   </deleteRow>
   <currentRow>
     <columnValue>100</columnValue>
     <columnValue>John</columnValue>
     <columnValue>Doe</columnValue>
     <columnValue>26</columnValue>
     <updateRow>20</updateRow>
   </currentRow>
</data>


    这个XML片断显示了第一行被<deleteRow>标签标记为删除。第二行第四列的值被标记出从当前值26更新为一个新值20。

提交更改

    迄今为止,我仅仅是操作结果。这些变化并不会反映到底层的数据库中,除非我进行了提交。下面代码,如果执行成功,将会通过提交是改变持久。

... ... ...
wrs.acceptChanges();
... ... ...


从XML读取

    WebRowSet也提供了一些readXML()方法,通过使用java.io.InputStream或者java.io.Reader实例从有效的XML文件中读取数据。如果你的输入数据是有效的XML形式,在进行其他处理之前需要将它们持久化到底层的数据库中,你就会发现这个选项非常有用。

使用WebRowSet的利弊

    在展示了WebRowSet的基础操作之后,我们总结以下使用这种方式操作数据的利弊。


+标准方案使它从不同的应用中生成和处理XML数据而不需要转化成为可能。
+数据操作的易用性——它支持滚动、更新、缓存和离线编辑。
+数据和XML简单转化使相关代码减少。较少的代码意味着较少的错误,也就意味着更加健壮的代码。
+较少的数据库更新可以帮助减少并发问题。


+性能和吞吐量可能会因为附加的信息如属性和元数据受到负面影响。在分布式应用中这可能是一个尤为突出的问题,因为巨大的XML文件需要在网络上传输以充分减少数据的数量。
+新的JDK版本,因为这个特征在1.4或者更老一些的JDK上并不可用。

适用性

    WebRowSet接口适合在下面情形中使用:
1、使用XML消息的应用集成,XML消息是当前顶级架构的选择之一。Java EE应用可以使用基于JMS的集成和其他外部通信,而使用JDBC保存自己的事务状态。在这样一个情形下,WebRowSet API减少了编程的复杂性,也降低需要编写的代码量。
2、来自持久性数据源的内容展示通常通过获取数据集并把它传递到视图组件(如JSP)中来完成。一个可用的方式就是在应用XSLT之前把数据集转化为XML,然后产生展示的内容。这种选择提供了更好的可维护性,因为它减少来自展示内容的组件的格式化。

总结

    直到最近,在数据库和XML之间来回的数据转化请求曾经是大部分应用开发和测试资源中一项主要任务。幸运的是,最新的JDBC API包含了一些特点例如数据集的精确导航、数据集的高速缓存、把数据集写入到XML中等等。对于企业级程序员RDBMS的重要性以及随着当前不断增长的Java和XML应用的普及度,像WebRowSet这样的接口提供的特征将会更加有用。那么,现在是时候重新考虑一下了,在下一个使用RDBMS作为数据持久化的Java/XML应用中,你是否仍然采用传统的数据访问方式;WebRowSet也许可以让你耳目一新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息