分享
 
 
 

使用 Apache Jakarta POI 从多个数据库创建一个 Excel 报表

王朝java/jsp·作者佚名  2006-04-07
窄屏简体版  字體: |||超大  

使用 Apache Jakarta POI 从多个数据库创建一个 Excel 报表

作者:Casimir Saternos

使用开放源代码技术将 SQL 广播到多个 Oracle 数据库,根据每个数据库结果集创建一个只有一个工作表的 Excel 工作簿。

本文相关下载:

示例代码和 JRE

Oracle 数据库 10g

Oracle JDBC 驱动程序

Apache Jakarta POI

微软的 Excel 电子表格广泛应用于当今的商业环境中。 尽管 Excel 能够读取和显示分隔文件,但 .xls 专有格式提供了其他一些富于表现力的特性,其中包括字体格式和多工作表电子表格。

许多商业和开放源代码的工具都提供了生成可由 Excel 读取的报表的功能。 比如,您可以使用 Oracle Reports 生成一个电子表格,或使用 SQL*Plus 输出一个由逗号分隔的文件。 利用现有的一些工具可以访问多个数据源。 但报表的格式与特定查询的结果紧密联系,而不同的数据源有时会生成不同的结果。 (比如,对两个不同数据库中的表进行 SELECT * FROM emp 查询,返回来的列的数量和类型将必然不同。) 出于各种各样的原因,您可能要访问几个不同的数据源,然后在一个电子表格中整理返回的结果:

数据库管理员可能希望比较不同数据库的配置。

应用开发人员可能需要检查不同数据库中 PL/SQL 对象的版本。

在数据库间移植数据时,数据库管理员可能需要估计作业的进度。

程序员使用测试数据库调试应用程序时,可能需要将当前数据与生产环境中的数据进行比较。

根据数据库的不同结构和用途,可能还有其它原因促使您想要生成此类电子表格,但所有原因都依赖于数据库的功能要求和定义。

本文将说明如何使用 Apache Jakarta POI 开放源代码项目从几个不同数据源生成一个电子表格。 工作簿中的每一个工作表将显示从某个给定 Oracle 数据库返回的结果。 在当前项目中您要达到的要求是:

运行该软件创建一个包含从一个或多个 Oracle 数据库获得的数据的电子表格。

用户将定义一个随意 SQL 查询,然后由各个配置的数据库处理该查询。

用户将定义一个或多个数据库连接。

生成一个配置文件,其中包括您定义的数据连接和 SQL 查询。

该配置文件的格式为 XML 格式。

将生成一个工作表显示每个数据库返回的结果。

将依据服务器名称和 Oracle 系统标识符(又称为 Oracle SID)命名每个工作表。

电子表格将以粗体显示列标题(基于数据库列)。

该软件将用 Java 编写。

将使用 JDBC 访问数据库。

将使用 Jakarta POI 生成电子表格。

您可以为生产系统添加许多要求。 很明显,上面的列表中遗漏了口令加密方面的内容。 虽然现在已经能够处理 SQL 数据类型,但是一个更健全的解决方案还应该能够处理一些特殊的数据类型,如 BLOB(二进制大对象)、CLOB(字符大对象)和 LONG。 目前只能调用一个 XML 配置文件和一个脚本来设置环境和执行 Java 类,还未提供易于使用的图形界面。 由于只执行一个查询,因此必须保证该 SQL 查询无语法错误,并基于每个数据库的对象返回一个结果集。 且记录的内容非常少。 尽管如此,如果程序达到了上面的要求,那么该程序还是相对容易使用的,并且它能够快速生成包含许多数据库数据的文档。 如果需要,还可以使用 Excel 编辑该文档的格式。 因为将多个数据源的数据纳入了一个电子表格中,所以我们可以很方便对从各数据库提取的数据进行比较了。 此外,您使用的主要机制即 POI 应用程序编程接口 (API) 调用清晰可辨,而不会被构建一个功能齐备的解决方案所需的其他代码和资源所淹没。

测试和要求

本文所生成的软件是在安装有 Java 运行时环境 (JRE) 1.4.2、运行 Windows 2000 系统的 PC 机上编写和测试完成的。(要了解 JRE 1.5 相关的问题,参见边栏) Java 的设计初衷就是实现平台无关性,所以在任何安装有适当 JRE 的机器上都应该能正常运行。 使用该版本的 JRE,您无需访问其他外部 API(如 Xerces 和 Xalan)就能利用 XML 处理。

JRE 1.5 应对措施

当结合 jdk1.5.0_04 使用该软件时,系统将抛出异常 java.lang.NoClassDefFoundError: org/apache/xpath/XPathAPI。 这是因为 org.apache.xpath.XPathAPI 类已经移植到了 JRE 1.5 中。 解决该问题的方法有两种:

使用含 XPathAPI 类的 jar,例如 xalan-2.4.1.jar。 将该 jar 加入到 CLASSPATH(类路径)。 这一方法同样适用于不含 XPathAPI 类的老版本 JRE。 这一方法有个缺点,就是要重新引用 JRE 中已有的功能。

更改源代码,移除包的限制条件。 将对 org.apache.xpath.XPathAPI 的引用变更为 XPathAPI。 (com.sun.org.apache.xpath.internal 中已经包含 XPathAPI )本方法需要另外下载 jar,也是本文采取的方法。

该软件用于运行客户端并访问远程 Oracle 服务器。 但请注意,从 Oracle 数据库第 8 版本开始,其中包含的 Java 虚拟机支持在数据库内使用 Java 对象。 利用这一功能,您可以灵活地开发与数据库环境紧密集成的客户端应用程序。 您可以使用 JDBC 来创建到任何数据库的连接,只要该数据库支持 JDBC 驱动。 这样一来,Oracle 数据库的功用就不仅限于数据库了,它可作为一个数据处理平台处理从各类数据源检索而来的数据。 本文中所用的软件将不使用这一功能,但当您根据自己的要求对本文所介绍的方法进行修改时,应该有意识的使用这一功能。

初始配置

如果系统中有几种 JRE,那么必须确保正确设置 PATH 环境变量,以调用 1.4.2 或更新版本的 JRE,而非老版本的 JRE。 可在 java.sun.com/j2se/1.4.2/docs/api 中 获取 JRE 1.4.2 版的 Javadoc 文档。

该软件下载中包含的批处理文件中的信息已经进行过更改,可用于 Linux 环境,而且这些信息已经在 Red Hat Linux 上测试通过。 只是对 run.sh 进行了适当的修改,并没有更改并执行 run.bat。 在 Linux 环境中,可使用 OpenOffice.org 的电子表格程序来显示电子表格。

环境设置基本上就是两个环境变量的设置: PATH 和 CLASSPATH。 首先要正确设置 CLASSPATH,以利用提供数据库访问和 Excel 电子表格功能的 API。 使用 run.bat 文件设置这一变量,这样就可以访问相应的 Java 文档(.jar 文件)。 您可能需要将指向 classes12.jar(其中包含 Oracle JDBC 驱动)的路径更改您系统上的正确路径。 在安装许多不同的 Oracle 产品时都将自动安装该文件。如果您系统中没有该文件,本文前面提供有文件的下载链接。 如果 CLASSPATH 不包含这一 jar,当程序试图载入 JDBC 驱动时,会出现错误:

Driver not found: oracle.jdbc.driver.OracleDriver

java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver

下载的文件中有一个 lib 目录,其中包含有 POI jar (poi-2.5.1-final-20040804.jar)。 如果 CLASSPATH 不包含这一文件,当程序试图创建一个工作表对象时,将出现以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError:

org/apache/poi/hssf/usermodel/HSSFWorkbook

The broadcast.jar 包含有一些文件,利用它们可以集中这些 API 的功能,然后基于配置的连接和 SQL 查询来 构建电子表格。 配置文件 (config.xml) 应该位于执行 broadcast.jar 的目录中。 如果不是,将出现错误(文件系统路径正确):

java.io.FileNotFoundException: C:\config.xml

(The system cannot find the file specified)

XML 配置

从 1.4 版本起,用于 XML 处理的 Java API 就已经加入了 Java 2 平台中。 利用该 API,可通过一系列标准的 Java 平台 API 来处理 XML 文档。 因此,当前项目也就无需另外添加 XML 处理包了。 只使用一个简单的配置文件就可以配置一个 SQL 查询和多个数据库连接。

XML 格式极其适用于配置文件,它使得配置数据易于您理解,可以通过标准的处理方法来顺利访问配置数据。 因为存储在配置文件中的数据很有限,也就不需要担心出现 "file bloat" 的情况。当使用 XML 标记符来标记大量数据时,会出现 "file bloat"。 此外, the hierarchical organization of our configuration data benefits from the organization allowed for through nesting entities in XML. 每个连接节点包含单一的数据,合用后就可以创建一个数据库连接。

下面是一个配置文件的示例:

<?xml version="1.0"?>

<broadcast>

<connection-config>

<database>

<server-name>server001</server-name>|

<port>1521</port>

<sid>ORCL</sid>

<username>sysdba</username>

<password>my1manager</password>

</database>

<database>

<server-name>server002</server-name>|

<port>1521</port>

<sid>PROD</sid>

<username>sysdba</username>

<password>my1manager</password>

</database>

</connection-config>

<sql-statement>select * from v$parameter</sql-statement>

</broadcast>

XMLConfigVO 类包含与读取和分析该 XML 文档的代码。 调用没有参数的构造器后,类将读取 config.xml 文件并创建一个新的 DocumentBuilderFactory实例。 本例没有使用 DTD(文档类型定义)或模式验证。 该厂生成了一个可供分析的文档对象,如果需要,还可操作该文档。

接下来将选择与 //broadcast/connection-config/database XPath 表达式的节点。 这些节点包含创建数据库连接所需的元素: 服务器名端口、Oracle SID、您名和密码。 最后,将使用//broadcast/sql-statement XPath 表达式进行查询,以获取 SQL 语句。 至此,利用存取器(getter 方法,其形式为 getXXXX())可以从 XMLConfigVO取回所有数据。

使用 JDBC

Java 数据库连接性 (JDBC) technology 是一个 Java API,它向 Oracle 数据库提供连接能力,以取回数据,用于填充电子表格。 JDBC API 还有一个特别之处,利用它还可在 Oracle 数据库间建立连接,用于发送 SQL 语句并处理结果。 本文中的程序只使用了这一 API 的部分功能,因为不需要执行 DML 或设置事务处理。 尽管支持所有类型的数据库,但这里我们要将处理限定到一个范围内,该范围内可清晰地映射到 Excel 电子表格。

Oracle JDBC 驱动依赖于 tnsnames.ora 或其他标准的 Oracle 客户连接信息。 只要系统中有 JRE 且 Oracle JDBC 驱动类存在于 CLASSPATH (且网络中有数据库),那么 Java 类就有足够的资源来创建到 Oracle 数据库连接。

classes12.jar 包含 Oracle 专用的 JDBC 驱动和类,它们也是本项目必须的要件。 它应该包含在 CLASSPATH 中,这样您才能够运行该程序。 你一般可以须 <ORACLE_HOME>/jdbc/lib 找到该文件,你也可以从 OTN 中下载 该文件。

OracleConnectionVO 类包含与 JDBC 连接相关的信息和处理。 oracle.jdbc.driver.OracleDriver 将是一个 URL,其形式为 jdbc:oracle:thin:@<serverName@>:@<Oracle Listener Port>:@<Oracle SID>,将通过它来创建连接。

Jakarata POI

正如我在 以前的文章中所述,Jakarta POI FileSystem API 以纯 Java 方式实施 OLE 2 复合文档格式,且通过 HSSF API 可以用 Java 来读写 Excel 文件。 在该篇文章中,使用了这一 API 来读取 Excel 文件。 这里我们将使用它来写一个 Excel 文件。 (POI 也为您提供了打开已有的电子表格并对它进行操作的功能)。 如果你想了解 POI 的列多功能,请参见 “HSSF 特性指南”,其中提供有代码实例,演示了开发人员经常需要的功能。

要创建一个工作表对象,调用以下代码(在 BroadcastDriver 类):

HSSFWorkbook wb = new HSSFWorkbook(fs);

在 POISheetGenerator 类完成调用,以创建工作表,然后它加入工作表中:

HSSFSheet sheet = wb.createSheet(sheetname);

列标题的字体为粗体,配置如下:

HSSFFont boldFont = wb.createFont();

boldFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

HSSFCellStyle boldStyle = wb.createCellStyle();

boldStyle.setFont(boldFont);

在与迭代与结果集相关的列时,将应用上面定义的单元格格式:

row.getCell((short) x).setCellStyle(boldStyle);

要将工作表写入磁盘中,调用以下代码:

OutputStream = new FileOutputStream("output.xls");

wb.write(out);

out.close();

broadcast.jar

broadcast.jar 包含了组成项目本身的类:

BroadcastDriver. BroadcastDriver 包含了用于这一应用程序的主要方法。 创建 HSSFWorkbook() 对象,该对象用于容纳所有的工作表。 然后创建 XMLConfigVO 对象,该对象用于从 config.xml 中读取连接和 SQL 查询。 使用该对象中包含的信息,应用程序将迭代每个 OracleConnectionVO 并设置 JDBC 驱动,JDBC 数据库 URL,数据库名称,数据库密码,SQL 查询和工作表的名称(形式为 <server name>-<Oracle SID>)。 填充有数据的工作表将加入工作表。 当所有连接迭代完成后,工作表将写入到文件系统中。

OracleConnectionVO. OracleConnectionVO 中保存了 JDBC 驱动、JDBC 数据库 URL、数据库名称、数据库密码和 SQL 查询的值。

XMLConfigVO. XMLConfigVO 创建 DocumentBuilderFactory 以分析 config.xml 文档。 XPath 查询用于检索包含所需值的 NodeList:

NodeList nodelist = org.apache.xpath.XPathAPI.selectNodeList(doc, xpath);

当找到正确的节点后,您可以调用 getNodeValue() 来取回它的值。

POISheetGenerator. 该类的 populateSheet 方法完成大部分的工作。 经过初始设置后,列标题将以粗体显示。数据库连接已经打开,查询将执行。

检索了元数据,我们需要元数据来确定将要迭代的列的数量。 元数据还包含了一些列的名称,这些名称将作为正在处理的工作表中的列名。 接下来将迭代结果集。 本例中的对各种数据的处理都是很初级的。 对于第个返回的对象,程序将试图以数字(特别是 Java 长字符)填充单元格。 如果出现 NumberFormatException 错误(因为该值不能转化为数字),将调用 toString,用于该返回对象。 toString 功能是在 Object 对象中定义的, Object 是 Java 体系的最底层,所以不管返回的是什么对象,都可以保证该方法的有效性。 但是,如果按照返回值对于对象的意义性和相关性来分析,那 toString 返回的实际值将是极其多样的。

潜在应用

下面提代了一些查询示例,可将它们加入 config.xml 文件中,以返回一些 DBA 或应用开发人员想在数据库间进行比较的数据。

V$DATABASE 表包含了数据库的一般信息,当您在比较数据库配置或解决备份和恢复的问题时,可能需要这些信息。 尽管不同版本的数据库的字段数和类型不同,以下的查询都可以顺利执行,并将显示合乎所指的表的结果:

SELECT * FROM v$database

如果一个 DBA 想记录一些数据库的版本信息,那么很可能要用到表 V$VERSION 的数据。 在这种情况下,可能要使用下下查询:

SELECT 'Name: '||name "Database Information" FROM v$database

UNION ALL

SELECT 'DBID: '||dbid FROM v$database

UNION ALL

SELECT * FROM v$version

在备份和恢复操作中,要关注的文件是主要有控制文件、重做日志文件和数据库数据文件本身。 你可以使用以下查询检索这些文件的位置:

SELECT * FROM

(

SELECT ' ' "Tablespace" ,Name "File Name" FROM V$CONTROLFILE

union

SELECT ' ', Member FROM V$LOGFILE

union

SELECT Tablespace_Name, File_Name FROM DBA_DATA_FILES

UNION

SELECT ' ' ,'****AS OF: ' ||to_char(sysdate, 'MM/DD/YYYY HH24:MI:SS')||'****' FROM dual

)

ORDER BY 1

Oracle Recovery Manager (RMAN) 一般用于管理备份和恢复操作。 当要检查备份活动,或相要实现备份活动的标准化时,你可能要用到数据库中存储的 RMAN 相关信息。 与 RMAN 备份相关的请求有:

SELECT * FROM V$BACKUP_SET

SELECT * FROM V$RMAN_CONFIGURATION

Oracle Applications DBA 在管理他们的环境时,可能会遇到一系列的问题。 DBA 如果管理的实例很多,那他们可能希望比较已经应用的补丁:

SELECT * FROM APPLSYS.AD_APPLIED_PATCHES ORDER BY PATCH_NAME

这些只是几种可能出现的情况。 任意的查询,只要没有句法错误,而且在数据库有其对应的对象,那么它就是可以执行的,返回的结果也可以显示在电子表格中。 这里提供示例对技术人员来说较有吸引力。 您也可以构想一些业务用途,比如访问特定应用的数据库对象和查询。

结论

Java 社区中提供了大量的资源,利用它们可以快速的创建程序(得益于众多历经验证的 API)。 利用 Oracle 的 JDBC 驱动,您可以使用 Java 编程语言方便的来访问数据库。而利用 Jakarta 编程人员创建的 POI,您可以直接创建带多表格式化和其他特性的 Excel 电子表格。 除了探讨这些技术外,文中所介绍的这个软件还能自动执行一些日常活动,可适当减轻 DBA 的工作负担。

Casimir Saternos 是 Oracle 认证 DBA、IBM 认证企业开发人员和 Sun 认证 Java 程序员,住在宾夕法尼亚州 Allentown。http://www.oracle.com/technology/global/cn/pub/articles/saternos_broadcast.html

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有