本文通过实验介绍了 JDBC 应用在不同版本 DB2 系统之间迁移的问题,探讨彼此的兼容性,并就存在的问题给出了解决办法。 关系数据库在您的电子商务应用中一定扮演着不可或缺的重要角色。DB2 是您的选择么?也许您的系统里早就部署了 DB2 UDB V7.2 系列软件;也许您正打算升级您的 DB2 系统到最新的版本;也许您刚刚部署了最新的 DB2 UDB V8.1 系列软件,并且想更新您之前开发的应用系统。如果您正打算这么做,那么这篇文章的话题应该是您所感兴趣的。 您的应用系统如果想和 DB2 系统打交道,我想首先需要做的一定是和 DB2 数据库建立连接并且对数据库进行各种操作。对于基于 JAVA 平台的应用程序来说,JDBC(Java Database Connectivity) 一定是开发人员的首选。它作为 JAVA 编程语言的必备组件,已经成为 JAVA 2 标准版(JAVA 2,Standard Edition,J2SE)规范的一部分,而 DB2 系统对 JDBC 做了很好的支持。 在您决定迁移您的应用系统的时候,可能并不想直接升级您的DB2系统到最新的版本,这个时候就可能会碰到和我开发中所碰到的相似的情形,即我们需要适应不同版本的 DB2 数据库同时存在的应用环境,这时我们可能希望应用程序能够顺利地在不同版本的 DB2 数据库之间迁移而无需做过多的修改。 本文就介绍了为解决这类问题所做的一系列实验,并且根据实验结果给开发人员提出了一些建议。 我们讨论的范围限定在使用 JDBC 连接 DB2 UDB V7.2 和 DB2 UDB V8.1 时碰到的问题。这里实验环境中的 JDK 版本是 1.3,可能有些开发人员已经尝试采用 JDK1.4 了,如果开发中碰到一些令人费解的问题,请尝试改变您的 JDK 版本再做尝试,这往往就能解决你的问题。 通过本文,读者可以了解到下面的一些知识: 1. DB2 系统对 JDBC (Java Database Connectivity)的支持 2. DB2 命令行工具 CLP(Command Line Processor) 3. DB2 命令中心(DB2 Command Center) 4. 不同版本 DB2 系统发布的 JDBC 驱动程序彼此的兼容性 我在实验中使用的软件系统包括: 1. IBM DB2 UDB V7.2 Enterprise Edition 2. IBM DB2 UDB V7.2 Enterprise Edition FixPack 7 3. IBM DB2 UDB V8.1 Enterprise Server Edition 4. IBM DB2 UDB V8.1 Enterprise Server Edition FixPack 4 5. IBM WSAD V5.0 6. Windows 2000 Server [url=]DB2 与 JDBC 支持[/url] 依照 JDBC 规范,有四种类型的 JDBC 驱动程序体系结构: Type 1:这类驱动程序将 JDBC API 作为到另一个数据访问 API 的映射来实现,如开放式数据库连通性(Open Database Connectivity,ODBC)。这类驱动程序通常依赖本机库,这限制了其可移植性。JDBC-ODBC 桥驱动程序就是 Type 1 驱动程序的最常见的例子。 Type 2:这类驱动程序部分用 JAVA 编程语言编写,部分用本机代码编写。这些驱动程序使用特定于所连接数据源的本机客户端库。同样,由于使用本机代码,所以其可移植性受到限制。 Type 3:这类驱动程序使用纯 JAVA 客户机,并使用独立于数据库的协议与中间件服务器通信,然后中间件服务器将客户机请求传给数据源。 - Type 4:这类驱动程序是纯 JAVA,实现针对特定数据源的网络协议。客户机直接连接至数据源。
对于DB2 UDB V7.2来说,它不支持 Type 1 和 Type 4 的驱动程序,但是提供了分别支持 Type 2 和 Type 3 的驱动程序。 示例如下: 两种驱动程序均随产品安装由 db2java.zip 提供。 - COM.ibm.db2.jdbc.app.DB2Driver
这是一种 Type 2 的 JDBC 驱动程序,它通过 DB2 本地客户机库的帮助建立和 DB2本地数据库或是远程数据库的连接(事先将远程数据库编目到本地)。因此,我们必须在应用系统所在的机器上同时部署 DB2 本地客户机库,这也许是它最大的一个不足之处。 使用格式如下: Driver Name:COM.ibm.db2.jdbc.app.DB2Driver URL Pattern:jdbc:db2:databasename databasename: 需要访问的数据库名 - COM.ibm.db2.jdbc.net.DB2Driver
这是一种 Type 3 的 JDBC 驱动程序,它通过与一台已经部署了 DB2 本地客户机库的机器通信来建立和 DB2 远程数据库的连接。 使用格式如下: Driver Name:COM.ibm.db2.jdbc.net.DB2Driver URL Pattern:jdbc:db2:ServerIP:databasename ServerIP: 需要访问的数据库所在机器IP地址 databasename: 需要访问的数据库名 (目标DB2系统侦听该服务于默认端口6789,否则还需要在 URL Pattern 中指定目标端口号) 对于 DB2 UDB V8.1 来说,它仍然不支持 Type 1 的驱动程序。同时,它在 DB2 UDB V8.1的基础上,新增加了对 Type 4 驱动程序的支持。 示例如下: DB2 UDB V8.1 仍然支持上面所述 V7.2 支持的两种驱动程序,随产品安装由 db2java.zip 提供,但具体实现上和 DB2 UDB V7.2 产品发布的包有所不同,所以可能存在下文所要进行实验验证的兼容性问题。 除了 COM.ibm.db2.jdbc.app.DB2Driver 之外,DB2 UDB V8.1 还提供了另外一种 Type 2 的驱动程序,随产品安装由 db2jcc.jar 提供。其实现包名是 com.ibm.db2.jcc.DB2Driver,在DB2 UDB V8.1 最初的实现中,此驱动程序只用于使用 Type 4 驱动程序体系结构与 DB2 服务器进行直接的 JAVA 连接,这类驱动程序由于不需要另外部署 DB2 本地客户机库以及性能相对较好而收到开发人员的欢迎。自从 DB2 UDB V8.1.2(安装了 FixPack 2)之后,开发人员还可以在 Type 2 体系结构中使用该驱动程序,以提高本地应用程序的性能。 这里,两种驱动程序具有相同的实现类名称,有两种不同的方法可以区分 DB2 系统在内部最终会实例化哪个驱动程序: - 使用不同的 URL Pattern 来区分两种不同的驱动程序
Type 2 Driver URL Pattern:jdbc:db2:databasename 这当中 databasename 是需要访问的数据库名 Type 4 Driver URL Pattern:jdbc:db2://ServerIP:50000/databasename 这当中 ServerIP 是需要访问的数据库所在机器IP地址,databasename 是需要访问的数据库名,DB2 服务器会在默认端口 50000 上进行侦听。 - 使用连接特性来区分数据库连接是否会使用 DB2 本地客户机库,或者是使用JAVA 直接连接。
DB2 UDB V8.1 新增加支持的这种 Type 4 驱动程序,常被称为“通用 JDBC 驱动程序”,是一种与驱动程序类型连通性或目标平台无关的抽象 JDBC 处理器,因此常用于进行分布式和本地 DB2 UDB 访问。因为“通用 JDBC 驱动程序”独立于任何特定 JDBC 驱动程序类型连通性或目标平台,所以它在一个 DB2 UDB 驱动程序实例中同时支持所有 JAVA 连通性(Type 4 驱动程序)和基于 JNI 的连通性(Type 2 驱动程序)。该驱动程序可以用于独立 JAVA 应用程序或多层应用程序,是开发人员一个不错的选择。 [url=]兼容性实验[/url] 上文前后介绍了很多种 DB2 系统支持的 JDBC 驱动程序,想必您的应用中已经采用了其中的某一种或几种,而在迁移您的应用时您一定希望最好不要更改原有的程序。这个要求能办到么?如果您的应用中所采用的驱动程序对不同版本的 DB2 系统进行连接的兼容性足够好,这个要求就一定能办到。那让我们带着这个疑问,来进行下面这个兼容性实验吧。 实验环境: 为了完成这个实验,我部署了两台机器,就分别命名为 Machine A 和 Machine B 吧。 Machine A 上部署了 DB2 UDB V7.2.7(安装了 FixPack 7),它可能和您应用环境中的旧版本 DB2 系统很类似;Machine B 上我部署了 DB2 UDB V8.1.4(安装了 FixPack 4,这是目前公开发布的最新的补丁),这也许和您升级后的最新 DB2 系统相仿。 相应的,在两台机器上,我都安装了 DB2 命令行工具(CLP),DB2 控制中心(Control Center),DB2 命令中心(Command Center)等工具以便能够对 DB2 系统进行配置和监控。 实验中当需要编写代码的时候,我采用的工具是 WSAD V5.0(WebSphere Studio Application Developer),这是个不错的开发工具。 实验目的: 我们带着上文碰到的这个问题来做这个实验。因此,我们分别采用上文中提及的各种 JDBC驱动程序尝试建立与 DB2 本地数据库和远程数据库的连接。如果一切顺利,这还只是完成了实验第一步。假设建立数据库连接成功,我们会紧接着尝试对这个数据库进行各种操作,先是测试查询操作,这是最常见的数据库操作;然后会是插入,更新,删除等 DML 操作,它们会改变数据库中存储的数据。如果这些都没有问题的话,我们还需要继续尝试诸如新建,修改,删除数据表等 DDL 操作。 为了增强实验的比较效果和准确性,我们除了会编写代码来进行各种测试,还会使用 DB2 命令行工具(CLP)和 DB2 命令中心(图形化管理工具)来进行相同的操作,并且就运行结果进行比较。 明确了实验目的,下面就来开始我们的实验吧。 实验过程: A:实验的第一步是测试 DB2 UDB 不同版本随产品发布的 JDBC 驱动程序对该版本自身的兼容性。 这里我先编写代码完成了各项测试目的,一切顺利。 然后,我使用 DB2 命令行工具(CLP)来重复这些测试。 可以通过在命令行中键入 db2cmd 进入 DB2 CLP,然后在提示符下键入 db2,就会进入DB2 CLP 的交互界面。 如下图: ![]()
这个命令行工具可以完成图形化工具所做的所有管理配置工作,并且可以节省很多内存资源。 实验中,我们首先需要用命令连接到一个数据库: 示例如下,在命令行提示符后键入 CONNECT TO SAMPLEDBUSER db2adminUSING password 该命令表示使用用户名为 db2admin,密码为 password,连接至数据库 SAMPLEDB,紧接着会返回连接后的数据库相关信息。然后就可以在命令行提示符后直接键入各种 DDL 或 DML 语句来执行各种操作。 最后,我们还可以使用 DB2 UDB 随产品发布的一个图形化管理工具――命令中心(Command Center)来验证我们的实验。 ![]()
可以参照上图启动命令中心,其相关操作请参见产品文档。 B:这一步我们将测试 DB2 UDB 两个版本中随产品发布的 Type 2 JDBC 驱动程序连接与其本身不同版本的 DB2 UDB 系统时的兼容性。 在进行这步测试时,由于 Type 2 JDBC 驱动程序是针对本地数据库开发的,因此我们需要先将远程数据库编目(catalog)到本地,再尝试连接。下面先给出了采用 DB2 命令行工具编目远程数据库的例子。 远程数据库的相关信息示例如下: 目标数据库所在机器名:TESTSERVER 目标数据库所在机器 IP 地址:10.1.1.15 目标数据库所属实例名:TESTINSTANCE 目标数据库名:SAMPLEDB 目标数据库所在机器操作系统类型:WINDOWS 启动 DB2 命令行工具 在命令行提示符下键入命令:
CATALOG TCPIP NODE TESTSERVERREMOTE 10.1.1.15 SERVER 50000REMOTE_INSTANCE TESTINSTANCEOSTYPE WINDOWS
此命令将 TESTSERVER 这台机器以及其中指定的数据库实例编目到本地 在命令行提示符下键入命令:
CATALOG DATABASE SAMPLEDBAT NODE TESTSERVER
此命令将样本数据库 SAMPLEDB 编目到本地 在命令行提示符下键入命令:
COMMIT 此命令将上面基本的修改提交给 DB2 系统使之生效。 - 在命令行提示符下键入命令:LIST DB DIRECTORY
通过这个命令你可以查看所有本地的数据库以及编目到本地的远程数据库的信息,以验证编目是否成功。 编目远程数据库之后,我们就可以将其看作是本地数据库对其进行各种操作。(如果想进一步了解这些命令的更多内容,可以参考 DB2 联机帮助) 这部分的测试结果比较有趣,在实验结果中会详细描述。 C:完成了上一步之后,我们已经有了不少收获。在这一步中,我们测试了 DB2 UDB 两个版本中随产品发布的 Type 3 JDBC 驱动程序连接与其本身不同版本的 DB2 UDB 系统时的兼容性。 在这步当中,我们直接采用 COM.ibm.db2.jdbc.net.DB2Driver 这种网络 JDBC 驱动程序来尝试连接远程数据库,均以失败告终。这无论是编写代码测试,还是 DB2 命令行工具,或者是 DB2 命令中心,都是令人沮丧的结果,因而这种方式不推荐大家使用。 D:最后这步也许是大家所最关心的,就是 DB2 UDB V8.1 新增支持的 Type 4 JDBC 驱动程序连接 DB2 UDB V7.2 时的兼容性(同时也支持Type 2 体系结构访问)。 这里我们将 DB2 UDB V7.2 作为远程数据库,采用 Type 4 JDBC 驱动程序直接进行连接,同样以失败告终。我们转而先将其编目到本地,采用该驱动程序的 Type 2 方式进行访问,其现象与用随 DB2 UDB V8.1 产品发布的 COM.ibm.db2.jdbc.app.DB2Driver 进行测试的结果类似。 这似乎让我们对这种新增支持的 JDBC 驱动程序失去了信心,不过不要着急。下文中会给出一种解决方法,能够使得这种驱动程序顺利的实现对 DB2 UDB V7.2 数据库的连接和各种操作。 附件中给出了测试代码的框架,请有兴趣的读者自行更改各种 JDBC 驱动程序的包名和 URL 模式以完成各种实验组合。 实验结果: A:对于这一类实验,我们对实验结果还是很有信心的,最后的实验结果也验证了我们事先的预想。 对于DB2 UDB V7.2 | DB2 UDB V7.2本地数据库 | DB2 UDB V7.2远程数据库 | COM.ibm.db2.jdbc.app.DB2Driver | 成功 | 成功 | COM.ibm.db2.jdbc.net.DB2Driver | 成功 | 成功 |
对于DB2 UDB V8.1 | DB2 UDB V8.1 本地数据库 | DB2 UDB V8.1 远程数据库 | COM.ibm.db2.jdbc.app.DB2Driver | 成功 | 成功 | COM.ibm.db2.jdbc.app.DB2Driver | 成功 | 成功 | com.ibm.db2.jcc.DB2Driver(Type 2) | 成功 | 成功 | com.ibm.db2.jcc.DB2Driver(Type 4) | 成功 | 成功 |
这步测试中,编写代码,DB2 命令行工具,DB2 命令中心测试结果一致。看来随产品发布的 JDBC 驱动程序对本产品的支持相当不错。 B:这类实验的结果差别还是比较大的,也比较有趣。 | DB2 UDB V7.2 远程数据库 (编目成本地数据库) | DB2 UDB V8.1 远程数据库 (编目成本地数据库) | COM.ibm.db2.jdbc.app.DB2Driver(随 DB2 UDB V7.2 产品发布) | 无意义 | 成功 | COM.ibm.db2.jdbc.app.DB2Driver(随 DB2 UDB V8.1 产品发布) | 连接成功,其它操作失败(CLP 除外) | 无意义 |
这步实验需要分两种情况来分析: 1. 本地端是 DB2 UDB V7.2 系统,远端是 DB2 UDB V8.1 系统,被编目至本地。 先用 DB2 命令行工具建立连接,进行各项数据库操作,都没有问题。 - 再用 DB2 命令中心重复上面操作,也没有问题。最后编写代码重复上面操作,同样一切正常。
这个结果让我们非常满意。
2. 本地端是 DB2 UDB V8.1 系统,远端是 DB2 UDB V7.2 系统,被编目至本地。 先用 DB2 命令行工具建立连接,进行各项数据库操作,一切正常。 再用 DB2 命令中心重复上面操作,数据库连接正常,但继续做数据库操作时,会报错:SQL0805N 找不到程序包 "NULLID.SYSSH200"。 SQLSTATE=51002,无法继续。 - 最后,编写代码进行测试,数据库连接一切正常,能够获得 Connection 对象引用,但是一旦进行各种数据库操作,会报和上面同样的错误。
这个错误将和下面实验 D 碰到的错误类似,下文会给出统一的解决方案。 C:这类实验之前我们猜测成功的可能性不大,最后的结果也验证了我们的猜测。 | DB2 UDB V7.2 远程数据库(未编目成本地数据库) | DB2 UDB V8.1 远程数据库(未编目成本地数据库) | COM.ibm.db2.jdbc.net.DB2Driver(DB2 UDB V7.2产品发布) | 与A重复 | 连接失败 | COM.ibm.db2.jdbc.net.DB2Driver(DB2 UDB V8.1产品发布) | 连接失败 | 与A重复 |
经过这步测试,可以认为直接用 COM.ibm.db2.jdbc.net.DB2Driver 连接不同版本的远程数据库是不合适的。 D:开发人员一定对 DB2 UDB V8.1 新增支持的这两种 JDBC 驱动程序期望值很高,因此这步实验的结果大家会比较关心。 | DB2 UDB V7.2 远程数据库(编目成本地数据库) | DB2 UDB V7.2 远程数据库(未编目成本地数据库) | com.ibm.db2.jcc.DB2Driver(Type 2) | 连接成功,其它操作失败(CLP 除外) | 无意义 | com.ibm.db2.jcc.DB2Driver(Type 4) | 无意义 | 连接失败 |
通过这步实验,这种最新支持的 JDBC 驱动程序在兼容低版本上与原有驱动类似。看到这个结果我们有点失望。 其实,这个问题的关键在于一些标准 JCC JDBC 程序包没有和目标数据库进行绑定,可以手工通过执行下面命令来完成这项工作。 示例如下: db2jdbcbind -url jdbc:db2://ServerIP:50000/SAMPLEDB -user db2admin -password password 使用该命令实现绑定相关程序包之后,我又重复了部分 实验 B 和实验 D,实验结果如下:
| DB2 UDB V7.2 远程数据库(编目成本地数据库) | DB2 UDB V8.1 远程数据库(编目成本地数据库) | COM.ibm.db2.jdbc.app.DB2Driver(DB2 UDB V8.1产品发布) | 成功 | 成功 |
| DB2 UDB V7.2 远程数据库(编目成本地数据库) | DB2 UDB V7.2 远程数据库(未编目成本地数据库) | com.ibm.db2.jcc.DB2Driver(Type 2) | 成功 | 无意义 | com.ibm.db2.jcc.DB2Driver(Type 4) | 无意义 | 成功 |
这同时解决了实验 B 和实验 D 中都碰到的问题,让我们松了一口气。 实验结论: 通过上面的实验,我们就可以得出这样一些建议。它适用于当您需要在不同版本的DB2系统之间迁移您的数据库应用的时候。 我们可以基于旧版本的 DB2 系统(如 DB2 UDB V7.2),然后将目标系统(如 DB2 UDB V8.1)编目至本地,使用 COM.ibm.db2.jdbc.app.DB2Driver 进行数据库连接和操作。 - 我们也可以基于新版本的 DB2 系统(如 DB2 UDB V8.1),然后将目标系统(如 DB2 UDB V7.2)编目至本地,先手工将相关程序包绑定至目标数据库系统,再使用 COM.ibm.db2.jdbc.app.DB2Driver 或是 com.ibm.db2.jcc.DB2Driver 进行数据库连接和操作。
实验的结果让我们较为满意,我们有了不只一种选择来迁移我们的应用。 注:由于时间和环境的限制,实验不可能覆盖所有的 JDBC 特性,而只限于较为常见的数据库操作。因此,可能在一些特殊情形下上面的实验结果并不成立,欢迎作进一步的讨论和补充。 [url=]小结[/url] 本文的作者在开发中碰到了 JDBC 数据库应用在不同版本 DB2 系统之间迁移的问题。带着这个问题,他进行了一系列实验,测试了 DB2 UDB V7.2 与 DB2 UDB V8.1 中 JDBC 驱动程序彼此的兼容性,并就存在的问题给出了解决办法。最后给有类似困惑的开发人员提出了一些建议。 |