使用 pureQuery 加速 Hibernate 和 iBATIS 应用程序,第 1 部分: 使用面向 Hibernate 和 pureQuery 的 IBM Integration Module

使用新集成模块实现静态 SQL 和异构批处理

当经过可下载的 IBM® Integration Module 扩展之后,IBM Optim® pureQuery Runtime 可以简化为 Hibernate 和 iBATIS 应用程序生成 DB2 静态 SQL 的过程。在此过程中,您无需更改您的应用程序代码或收集来自生产工作负载的 SQL。Optim pureQuery Runtime 还支持访问 DB2 或 Informix® 的 Hibernate 和 iBATIS 应用程序,以从 pureQuery 中的异构批处理特性中获益。借助异构批处理特性,在沿网络发送多个 INSERTUPDATEDELETE 请求之前,甚至在请求引用多个表时,可以对其进行批量处理。本文是一个包含两部分的系列文章的第一部分。它介绍如何对 Hibernate 应用程序使用 IBM Integration Module。第二部分将专注于 iBATIS 应用程序。本文包含一个可下载的样例应用程序,展示如何轻松实现两种功能。本文还提供了非正式的运行时性能度量。

Sandhya Turaga, 软件工程师, IBM China

Sandhya Turaga 的照片Sandhya Turaga 是 IBM 硅谷实验室的对象查询开发团队的一名软件工程师。之前在 IBM 实习期间,她一直致力于 ObjectGrid 的对象查询语言的查询性能改进。她于 2008 年 5 月毕业于圣何塞州立大学,取得计算机科学硕士学位,其论文课题是网格计算。



Abhigyan Agrawal, 软件工程师, IBM China

Abhigyan Agrawal 的照片Abhigyan Agrawal 是 IBM 硅谷实验室的开源团队的一名软件工程师。他目前致力于为 Hibernate 提供 DB2 静态 SQL 支持。之前主要致力于在 iBATIS 中提供 DB2 静态 SQL 支持并开发 IBM Python 驱动程序。他毕业于班加罗尔的印度国际信息学院,具有信息技术硕士学位。



Kathy Zeidenstein, 高级软件工程师,Enablement, IBM

作者照片:Kathy ZeidensteinKathy Zeidenstein 在 IBM 工作了很多年。目前她在 IBM Data Studio 支持团队工作。在担任这个职务之前,她是 IBM OmniFind Analytics Edition 的产品营销经理。



Mario Briggs, 资深软件工程师, IBM China

Mario  Briggs 的照片Mario Briggs 负责 IBM DB2 和 IBM Informix 的开源服务,包括 PHP、Ruby/Rails、Python/Django/SqlAlchemy、Perl 和 Java 数据访问框架。Mario 有 11 年的软件开发经验,其中有多年主要专注于数据访问、关系引擎和应用程序数据库性能领域。



2010 年 11 月 24 日

概述

pureQuery 是一个高性能数据访问平台,包含开发工具、一个 Java® API、一个运行时以及监控服务。使用轻量级 pureQuery API,您可以编写访问 DB2、Informix 甚至是 Oracle 数据库的数据访问代码。不过,pureQuery 的许多优势 — 可视化和修改所生成 SQL 的能力,对数据库访问最佳实践的使用,对异构批处理等性能特性的支持,以及通过查询收集性能数据的能力 — 不需要使用 API。有关 pureQuery 的更多信息,请参阅 参考资料 部分。

对现有应用程序使用 pureQuery 的一个关键用例是 DB2 数据服务器,在该服务器中您可以将 SQL 执行模式从动态执行(Java 应用程序的默认模式)转换为静态执行。这样就无需在运行时执行准备工作,且可以减少 SQL 注入风险。有关静态执行优势的更多信息,请参阅 参考资料 部分。

对于 pureQuery,您可以利用 Optim Development Studio 功能,比如可视化性能指标,将生成的 SQL 语句与原始的 Java 源码相关联。这使 pureQuery 有利于供访问 Informix 和 Oracle 数据库的现有应用程序使用。图 1 是 Optim Development Studio 的一幅屏幕截图,其中突出显示了一些关键功能。

图 1. Optim Development Studio 概览图
该屏幕截图显示 Java 源码中的一个查询与架构(数据库标签中)中的引用表之间的关联。语句的性能指标在该数据库标签上也有显示。

有关 Optim Development Studio 优势的更多信息,请参阅 参考资料 部分。

对于并非由 pureQuery API 编写的现有应用程序,有两种使用 pureQuery 的方式。您可以独立或组合使用这些方法:

  • 使用客户端优化 流程来让 Optim pureQuery Runtime 在 Java 程序运行时捕捉 SQL(以及相关的性能和应用程序元数据)。该方法的灵活性在于,您可以对任何 Java 应用程序(包括套装软件)使用它。但是,它需要一些额外设置,且需要在代码中执行各种路径以确保捕捉所有 SQL。捕捉 SQL 之后,您可以使用 Optim Development Studio 的完整功能修改 SQL、可视化访问路径、执行性能测试并进行影响力分析。参考资料 部分包含一个教程链接,该教程介绍如何使用客户端优化流程。
  • 使用集成模块 来支持程序利用 pureQuery 和 Optim Development Studio 的完整功能,而无需以一个初始的捕捉步骤。这是一种新方法,且是本系列文章的重点。通过这种方法,集成模块可以在 Hibernate/iBATIS 程序运行之前捕捉 SQL 及其元数据。该支持之前可用于 WebSphere® OpenJPA(参阅 参考资料 部分获取相关主题的文章链接)。现在,随着新集成模块的出现,该支持也可用于 Hibernate 和 iBATIS 应用程序。有了这些模块,您可以使用工具可视化和优化 SQL,而无需执行运行时捕捉(您可以连同捕捉步骤一同使用它,如 使用增量捕捉模式收集 Criteria 查询 部分所述)。

面向 Hibernate 和 pureQuery 的 IBM Integration Module 为 Hibernate 应用程序提供以下优势:

  • 您的 Hibernate 应用程序可以使用静态 SQL 而无需初始的 pureQuery 客户端优化捕捉。Integration Module 生成 Hibernate 应用程序使用的 SQL。可以静态绑定 SQL 来访问 DB2 数据库,且可以审查、共享、优化和替换 SQL,而无需更改应用程序本身。也可以将 SQL 与应用程序代码相关联来追踪造成性能问题的 Hibernate 源码,或者将 SQL 与数据库对象更改相关联来使用 Optim Development Studio 进行影响力分析。
  • 您的 Hibernate 应用程序可以使用 pureQuery 中的异构批处理特性。该特性支持您批量处理多个 INSERTUPDATEDELETE 请求,甚至在这些请求引用多个表时亦是如此。例如,要更新雇员对象,就需要更新组成该对象的若干数据库表,这可在一个(而非多个)数据库往返行程中完成。每个从网络到数据库服务器的往返行程从性能角度来看是昂贵的。因此减少往返行程而多多采用批量处理对于性能更有益。这个支持可用于 DB2 和 Informix 数据库。

本文描述如何设置和使用面向 Hibernate 和 pureQuery 的 Integration Module。首先介绍了集成模块的静态 SQL 特性,之后描述了异构批处理特性。本文假定您有一定的 Hibernate 知识且您在使用 Hibernate 3.2 或更高版本。您可以利用 Integration Module 提供的优势,而无需更改应用程序代码。

何为静态 SQL 且它如何有助于性能提升?

DB2 中的静态 SQL 是一个强大的功能,能使您在运行时精简数据访问。具体表现就是提前执行一些工作,比如确定数据库访问路径。这有助于运行时以更一致的方式更快地执行。图 2 显示了动态 SQL 执行与静态 SQL 执行的对比。

图 2. 静态 SQL 执行与动态 SQL 执行之对比
动态 SQL 流程图显示有 6 个步骤,而静态 SQL 流程图仅有 3 个步骤。

静态 SQL 与动态 SQL 的安全模型也不同。对于静态 SQL,用户仅接收权限来执行绑定过程的输出,也称为程序包。该包包含 SQL 语句。因此,如果对一个表的所有访问都是静态的,您仅需要授权给程序包,而非整个表和视图。另外,通过使用静态 SQL,您可以降低恶意注入 的机会,这是动态 SQL 的一个众所周知的安全问题。

有关静态 SQL 的更多信息,请参阅 参考资料 部分。


使用面向 Hibernate 和 pureQuery 的 Integration Module 创建静态 SQL 的概述

本节比较 Hibernate 应用程序的一个默认执行(动态 SQL)与使用 Integration Module 来创建和使用静态 SQL 的执行。

Hibernate 的动态 SQL 执行:JDBC

图 3 显示不使用 Integration Module 的 Hibernate 应用程序的高级执行。Hibernate 生成 SQL 语句字符串并使用 JDBC 准备和执行操作在数据库中执行它们。

图 3. 不使用 Integration Module 的 Hibernate 应用程序的动态 SQL 执行
Hibernate 应用程序生成 SQL 字符串,经由 JDBC 驱动程序到达数据库。

使用 Integration Module 的 Hibernate 静态 SQL 执行:pureQuery

图 4 显示使用 Integration Module 的 Hibernate 应用程序的高级执行。DB2 程序包是专为静态 SQL 执行而创建的。该图描述以下内容:

  • 一个 SQL 生成步骤(HibernateGen)收集 Hibernate 应用程序在一个 pureQuery XML 文件(这些文件有一个 .pdqxml 文件类型)中使用的所有 SQL。然后可在 Optim Development Studio 中使用该文件进行调优或影响力分析,而无需一个 BIND 步骤。可以使用 Static Binder 将 pureQuery XML 捕捉文件绑定到静态程序包中。
  • 在应用程序执行期间,pureQuery Runtime 重定向 JBDC 调用来执行生成步骤中创建的 DB2 静态程序包。pdq.properties 文件控制 pureQuery Runtime 执行行为(动态或静态)且提供 pureQuery XML 文件的位置。
图 4. 使用 Integration Module 的 Hibernate 应用程序的静态 SQL 执行
HibernateGen 创建 pdqxml,然后 pdqxml 在 DB2 中创建静态程序包。pureQuery 重定向 JDBC 调用来执行静态程序包。

从一个 Hibernate 应用程序中可以提取哪些 SQL 语句?

以下 SQL 语句可由 Integration Module 提取:

  • 命名 SQL 查询 — 使用 Java Persistence Query Language (JPQL) 和 Hibernate Query Language (HQL)
  • 命名原生 SQL 查询 — 命名 SQL 查询,使用 Java Persistence API (JPA) 和指定的 Hibernate API
  • Hibernate Beans/实体的 Create、Read、Update 和 Delete (CRUD) 操作的 SQL 语句 — 使用 JPA 和本机 API
  • Hibernate Beans/实体中对 Collections 的 CRUD 操作的 SQL 语句 — 使用 JPA 和本机 API

Integration Module 不生成标准 SQL 查询和内嵌 SQL 查询。您应当避免在 Java 代码中嵌入 HQL 查询,除非它们是真正的动态查询。在这种情况下,不能对这些查询应用静态 SQL。有关外化 HQL 查询的更多信息,参阅 参考资料 部分。


何为异构批处理且它如何有助于性能提升?

Hibernate 使用 JDBC 进行数据访问。JDBC 支持一种名为异构批处理的 批处理形式。这种形式的批处理仅限于单个表以及同一 SQL 语句的多个执行,前提是该语句有输入参数。但是,在一个事务中更新多个实体类型时,或使用涉及次级表、联合继承或每类一表继承的实体映射时,一个事务可以包含涉及多个表的 SQL 语句。因此在这种情况下,JDBC 批处理无效。

此外,只要 SQL 语句没有 任何输入参数,JDBC 批处理仅支持添加不同的 SQL 语句到批处理中。不过,使用 Hibernate(或 OpenJPA)的典型应用程序出于动态性会使用 输入参数的 SQL 语句。在这些场景中,JDBC 支持对不同的 SQL 语句进行批处理。

下面看一下批处理场景,如清单 1 所示。

清单 1. 批处理场景
PreparedStatement pstmt = conn.prepareStatement("update T1 set name=? where id=?");
pstmt.setString(1,"name1");
pstmt.setInt(2,1);
pstmt.addBatch();

pstmt.setString(2,"name2");
pstmt.setInt(2,2);
pstmt.addBatch();

pstmt.executeBatch();

您不能添加 SQL 语句 delete from T1 where ID = ? 到清单 1 所示的批处理中。而是需要另外创建一个 preparedStatement 来执行删除操作,且另外会有一条消息被发送到数据库服务器来准备删除查询语句。

对于 JDBC 批处理范围以外的情况,您可以使用 pureQuery 支持的异构批处理 来提高性能。例如,再次看一下清单 1 中显示的场景。您可以使用 pureQuery 添加清单 2 中的 SQL 语句到相同的 pureQuery 批处理任务中。然后 pureQuery 会负责准备语句并在一条消息中将所有语句发送到数据库服务器。这可以提高性能。

清单 2. 异构批处理
update T1 set name=? where id=?
delete from T1 where ID = ?

表 1 总结了可利用 pureQuery 异构批处理的程序的一些特征。

表 1. pureQuery 异构批处理有用的场景
程序特征受 JDBC 同构批处理支持?受 pureQuery 异构批处理支持?
批量更新映射到多个表的实体
对同一表的不同列执行批量更新否(除非使用文字而非输入参数)
对同一表批量执行多个操作(INSERTUPDATEDELETE否(除非使用文字而非输入参数)
对多个实体执行批量更新否(除非使用文字而非输入参数)

异构批处理不为以下场景提供额外的应用程序性能:

  • 应用程序仅包含 SELECT 语句。这是因为当前版本的 Integration Module 中的异构批处理仅提高 INSERTUPDATEDELETE 语句的性能。
  • 应用程序使用带有表标识或数据库序列密钥生成器的实体。

使用 Integration Module 实现异构批处理的概述

本节比较使用和不使用 pureQuery 异构批处理的 Hibernate 应用程序的执行。

Hibernate 中的默认批处理:JDBC

图 5 显示不使用 pureQuery 异构批处理的 Hibernate 样例应用程序的高级执行流。(样例应用程序可从 下载 部分获取。) Hibernate 生成 INSERTUPDATEDELETE 语句字符串并将它们传递给类持续程序以便执行。持续程序调用批处理程序来执行 JDBC 准备和执行操作。

图 5. 不使用 pureQuery 异构批处理的 Hibernate 应用程序的执行
fHiberntae APIs 通过批处理程序和持续程序执行实体操作。然后经由 jdbc 驱动程序到达数据库。

Hibernate 中的异构批处理:pureQuery

图 6 显示使用 pureQuery 异构批处理的 Hibernate 样例应用程序的高级执行流。Hibernate 生成 INSERTUPDATEDELETE 语句字符串,将它们传递给类持续程序以便执行。

IBM Integration Module 实现批处理程序、事件侦听程序和持续程序的接口,以支持传送 SQL INSERTUPDATEDELETE 语句到 pureQuery 而非 JDBC,并利用 pureQuery 批处理的优势。在将所有 SQL 语句从一个事务添加到批处理任务中之后,FlushListener 通知批处理程序执行批处理。当前版本的 Integration Module 不支持 SELECT 语句的异构批处理,因此这些语句不流经定制的批处理程序和持续程序。

图 6. 使用 pureQuery 异构批处理的 Hibernate 应用程序的执行
经由侦听程序、批处理程序和持续程序的操作;经过 pureQuery 运行时;经过 SQL 和 JDBC 数据服务器驱动程序;最后到达数据库

使用面向 Hibernate 和 pureQuery 的 IBM Integration Module 的先决条件

参考资料 部分包含一个链接,您可以通过该链接下载面向 Hibernate 和 pureQuery 的 IBM Integration Module。

软件

要使用 pureQuery Integration Module,您必须具备:

  • Optim pureQuery Runtime 2.2.0.3 或更高版本(参阅 参考资料 部分,通过一个链接下载 IBM Optim Development Studio 和 Optim pureQuery Runtime 的 30 天试用版。运行时必须与 Optim Development Studio 位于同一台主机上。)
  • 确保在类路径中有 pdq.jar 和 pdqmgmt.jar。
  • IBM Data Server Driver for JDBC 和 SQLJ 3.58 或 4.7(Optim Development Studio 提供,或参阅 参考资料 部分获取下载链接)。
  • Hibernate 3.2 或更高版本。

Integration Module 包含一个验证工具,可用来检查先决条件。参阅 使用 versionValidator 工具检查先决条件 部分,了解如何使用该工具。

受支持的数据库

面向 Hibernate 和 pureQuery 的 IBM Integration Module 在应用程序访问以下数据库系统时有效:

  • DB2 for Linux®, UNIX®, and Windows® V8.2,Fix Pack 11 或更高版本
  • DB2 for Linux, UNIX, 以及 Windows V9.1、V9.5 或 V9.7
  • DB2 for i V5R4(仅针对异构批处理特性)
  • DB2 for z/OS® V8 或更高版本
  • Informix Dynamic Server V11.10 或 V11.5(仅针对异构批处理特性)

本文中使用的样例应用程序

下载 部分的 DemoHibApp.zip 文件包含一个样例应用程序,如果您在使用 Hibernate 3.2 或更高版本,您可以使用它来试用这个功能。


为 Hibernate 应用程序启用 pureQuery 静态 SQL

本节使用 Hibernate 样例应用程序来阐述如何使用 IBM Integration Module 处理静态 SQL。

persistence.xml 中的编辑提供程序

如果您在使用 persistence.xml,为了启用 pureQuery 静态 SQL 支持,您需要确保在 persistence.xml 中指定提供程序属性。

对于样例应用程序,该属性已得到设置,如清单 3 中的第一行所示。

清单 3. 启用 pureQuery 静态 SQL 所需的 persistence.xml 中的必要属性
<provider>com.ibm.pdq.hibernate3.PDQHibernatePersistence</provider>
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->

如果您在使用 hibernate.cfg.xml,就没有必要对它进行任何更改。

为何启用 Hibernate 静态 SQL 需要提供程序变更?

静态 SQL 的使用需要 Hibernate 生成的 SQL 字符串每一次都完全相同。Hibernate 中有一个已知问题,导致 Hibernate 在应用程序运行中生成具有不同列别名的相同 SQL。(欲了解详细信息,参阅 Hibernate 网站上的这个论坛帖子:how are column alias names generated。)

为了启用静态 SQL,您需要通过以下方式解决该问题:

配置类路径

样例应用程序使用 Hibernate 3.2、Hibernate 实体管理器和 Hibernate 注释。因此,要编译应用程序,您需要类路径中的以下 jar 文件以及 Hibernate 所需的其他 jar 文件:

  • hibernate3.jar
  • hibernate-entitymanager.jar
  • hibernate-annotations.jar
  • hibernate-common-annotations.jar
  • ejb3-persistence.jar
  • dom4j-1.6.1.jar
  • log4j-1.2.15.jar
  • javassist-3.4.GA.jar
  • antlr-2.7.6.jar
  • commons-collections-3.1.jar
  • slf4j-api-1.5.2.jar
  • slf4j-log4j12-1.5.2.jar
  • commons-logging-1.0.4.jar
  • pdq-hibernate3.2.jar (shipped with the integration module)

要使用 IBM Integration Module,您还需要类路径中的以下 jar 文件:

  • pdq.jar
  • pdqmgmt.jar
  • The db2jcc jars

使用 versionValidator 工具检查先决条件

Integration Module 包含一个名为 versionValidator 的程序,它为 Hibernate、JDBC 驱动程序和 pureQuery 运行时的版本执行一个类路径的先决条件检查。清单 4 显示运行程序的命令。

清单 4. 运行 versionValidator 程序的命令

java  com.ibm.pdq.hibernate3.utility.VersionValidator

如果类路径中包含的 jar 文件适当,versionValidator 程序显示类似清单 5 中的消息。

清单 5. 所有先决条件正确时 versionValidator 程序的输出
>set CLASSPATH=./pdq.jar;./pdqmgmt.jar;./hibernate3.jar;./db2jcc.jar;./pdqhibernate3.jar;

>java    com.ibm.pdq.hibernate3.utility.VersionValidator

IBM integration module version: 2.2.0.3

Hibernate version: 3.3.1.GA

Found pdqmgmt.jar

PDQ runtime version: 2.18.121

IBM DB2 JDBC Universal Driver: 3.53

java version: 1.5.0_13

如果类路径中包含的 jar 文件不适当,versionValidator 程序显示一条相应的错误消息。例如,清单 6 中的消息表明,DB2 JDBC 驱动程序不适合使用 Integration Module。

清单 6. 具有错误先决条件的 versionValidator 程序的输出
Hibernate version: 3.3.1.GA

Found pdqmgmt.jar

PDQ runtime version: 2.1.70

Found IBM DB2 JDBC Universal Driver version: 2.3 **** ERROR. Incorrect level. Requires 
        V3.53 or higher

java version: 1.5.0_13

准备样例应用程序的数据库

遵循以下步骤来准备样例应用程序的数据库:

  1. 创建一个名为 demodb 的数据库。 Hibernate 自动创建所需的表。
  2. 解压 DemoHibApp.zip 文件并将样例应用程序作为一个 Java 项目导入 Optim Development Studio 工作空间。
  3. 配置类路径 中列出的相同的 jar 文件包含在项目构建路径中。您可以右键单击项目并选择 pureQuery > Add pureQuery support...,为 pureQuery 和 IBM Data Server 添加 JDBC 和 SQLJ jar 文件。

样例应用程序使用以下实体:

  • CustomerInfo with subclass Customer
  • District
  • Item
  • Order

为静态 SQL 执行生成 pureQuery XML 文件

使用 HibernateGen 命令为样例应用程序生成一个 test.pdqxml 文件。 命令(HibernateGen.bat)的批处理文件随附在 Integration Module 中。您的类路径需要包含 Hibernate 需要的所有 jar 文件,包括以下文件:

  • pdq-hibernate3.3.jar
  • pdq.jar
  • pdqmgmt.jar and db2jcc.jar

如果您在使用 persistence.xml,清单 7 显示用于设置类路径的命令,以包含所需的 jar 文件并执行 HibernateGen 命令。

清单 7. 使用 HibernateGen 为 persistence.xml 生成 pdqxml 文件
> set CLASSPATH=./pdq.jar;./pdqmgmt.jar; ./db2jcc.jar;./pdq-hibernate3.3.jar;
./hibernate3.jar;./hibernate-entitymanager.jar;./hibernate-annotations.jar;
./hibernate-common-annotations.jar;./ejb3-persistence.jar;./dom4j-1.6.1.jar;
./log4j-1.2.15.jar;./javassist-3.4.GA.jar;./antlr-2.7.6.jar;
./commons-collections-3.1.jar;./slf4j-api-1.5.2.jar;./slf4j-log4j12-1.5.2.jar;
./commons-logging-1.0.4.jar;%CLASSPATH%

> HibernateGen -puName test

如果您在使用 hibernate.cfg.xml,那么使用清单 8 所示的命令来设置类路径并执行 HibernateGen 命令。

清单 8. 使用 HibernateGen 为 hibernate.cfg.xml 生成 pdqxml 文件
> set CLASSPATH=./pdq.jar;./pdqmgmt.jar; ./db2jcc.jar;./pdq-hibernate3.3.jar;
./hibernate3.jar;./hibernate-entitymanager.jar;./hibernate-annotations.jar;
./hibernate-common-annotations.jar;./ejb3-persistence.jar;./dom4j-1.6.1.jar;
./log4j-1.2.15.jar;./javassist-3.4.GA.jar;./antlr-2.7.6.jar;
./commons-collections-3.1.jar;./slf4j-api-1.5.2.jar;./slf4j-log4j12-1.5.2.jar;
./commons-logging-1.0.4.jar;%CLASSPATH%

> HibernateGen

完成 HibernateGen 命令之后,检验是否在 src 目录中创建了一个名为 test.pdqxml 的文件。

注意:HibernateGen 生成的 SQL 以 JDBC 为 resultsetHoldability 的默认值。不过,WebSphere Application Server 使用一个不同的 resultsetHoldability 默认值。如果您要将自己的 Hibernate 应用程序部署到 WebSphere Application Server 上,检查 WebSphere Application Server 数据源的 resultsetHoldability 并在 HibernateGen 命令中指定它,如清单 9 所示。

清单 9. HibernateGen for WebSphere Application Service 默认设置
    > HibernateGen -resultsetHoldability 2

HibernateGen 命令还有大量其他选项可供使用。要获取所有可用选项列表,执行 HibernateGen 命令的 -help 选项,如清单 10 所示。

清单 10. 列出 HibernateGen 命令的选项
    > HibernateGen -help

为静态 SQL 执行配置和绑定 pureQuery XML 文件

为了静态地运行静态应用程序,您首先需要配置和绑定生成的 test.pdqxml。为此,可以使用标准 pureQuery ConfigureStaticBinder 命令,如清单 11 所示。 StaticBinder 命令在 DB2 服务器上创建程序包。在运行这些命令时,要确保 pdq.jar、pdqmgmt.jar 和相应的 JCC 驱动程序 jar 文件位于类路径中。有关 pureQuery ConfigureStaticBinder 命令的更多信息,参阅 参考资料 部分。

清单 11. 配置和绑定 pureQuery XML 文件
> java com.ibm.pdq.tools.Configure -rootPkgName test -pureQueryXml test.pdqxml

> java com.ibm.pdq.tools.StaticBinder

  -url jdbc:db2://localhost:50000/demodb

  -username xx

  -password xx

  -pureQueryXml test.pdqxml

  -traceFile demo_trace.txt

  -traceLevel ALL

使用静态 SQL 运行应用程序

清单 12 显示样例应用程序中包含的 pdq.properties 文件使用的属性。

清单 12. 样例应用程序的 pdq.properties 文件
pdq.captureMode=OFF
pdq.executionMode=STATIC
pdq.pureQueryXml=test.pdqxml

以下是设置描述:

  • captureMode=OFF 表示该捕捉模式已关闭。只有在使用客户端优化流程(本文后面会有介绍)时才需要打开捕捉模式。
  • executionMODE=STATIC 表示应当使用静态(而非动态)执行模式。
  • pureQueryXml=test.pdqxml 提供运行 HibernateGen 命令时创建的第三个 pureQuery XML 文件的名称和位置。

关于所有 pdq 属性的更多信息,参阅 参考资料 部分。

在样例应用程序中包含的实际 pdq.properties 文件中,所有属性都经过注释(每一行都以 # 开头)。在继续之前,编辑文件,删除 # 符号来取消对三个属性的注释,然后保存文件。完成之后,文件应当如清单 12 所示。

如果您在使用 persistence.xml,可以通过执行 MainClient.java 来运行样例应用程序。要在 Optim Development Studio 上运行 MainClient.java,右键单击文件并选择 Run As > Java Application。应用程序上的 SQL 语句被静态执行。

如果您在使用 hibernate.cfg.xml,可以通过执行 MainClientSessionFactory.java 来运行样例应用程序。注意,hibernate.cfg.xml 使用 Integration Module 提供的 Configuration 类,如清单 13 所示。这用来解决 为何启用 Hibernate 静态 SQL 需要提供程序变更? 部分描述的问题。

清单 13. 在 hibernate.cfg.xml 应用程序中使用 Integration Module 提供的 Configuration 类
public static void main(String[] args) {
	
    _sFactory = new PDQAnnotationConfiguration().configure()
						.buildSessionFactory();

如果您在 WebSphere Application Server 上部署和运行样例应用程序,参阅 参考资料 部分,获取有关 Web 应用程序环境中的 pureQuery 客户端优化的链接。


为 Hibernate 应用程序启用 pureQuery 异构批处理

在 persistence.xml 中设置属性

要使用 IBM Integration Module 对 Hibernate 3.2 应用程序启用 pureQuery 异构批处理,您需要确保在 persistence.xml 文件中指定以下属性:

  • 必须将 hibernate.jdbc.factory_class 设置为 com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory
  • 必须将 hibernate.ejb.event.flush 设置为 com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener

样例应用程序在 persistence.xml 的一个注释部分包含这些属性。因此对于样例应用程序,您只需编辑 persistence.xml 文件,取消对这些属性的注释并保存文件。删除注释之后,文件的这个部分类似于清单 14。

清单 14. 启用 pureQuery 批处理所需的 persistence.xml 中的必要属性
<property name="hibernate.jdbc.factory_class" value = 
"com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory"/>

<property name="hibernate.ejb.event.flush" value = 
"com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener"/>

<property name="hibernate.connection.provider_class" value= 
"org.hibernate.connection.C3P0ConnectionProvider"/>

配置语句缓存

为了实现最佳性能,启用语句缓存并为其设置一个合理大小很重要。Hibernate 应用程序可以使用 c3p0 连接池来启用 J2SE 应用程序中的语句缓存。要启用 c3P0 语句缓存,在 persistence.xml 中将 hibernate.connection.provider_class 设置为 org.hibernate.connection.C3P0ConnectionProvider,如清单 14 所示。

对于 J2EE 应用程序,您可以在应用程序服务器上设置语句缓存。

c3p0.properties 文件指定语句缓存的大小,如清单 15 所示。

清单 15. c3p0 文件大小规定
c3p0.maxStatementsPerConnection = 200

您为语句缓存指定的大小应当相对较大,一般在 100 到 200 之间。在一个 J2SE 环境中,如果语句缓存太小或批量太大,您可能会因语句缓存中的不一致性而收到 SQL 异常。

配置 hibernate.cfg.xml

如果您的 Hibernate 应用程序在使用原生 Hibernate API,您必须在 hibernate.cfg.xml 文件中指定以下属性:

  • 必须将 hibernate.jdbc.factory_class 设置为 com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory
  • 必须将 flush event listener 类设置为 com.ibm.pdq.hibernate3.listener.PDQFlushListener

样例应用程序在 hibernate.cfg.xml 的注释部分包含属性。因此对于样例应用程序,您只需编辑 hibernate.cfg.xml 文件,取消对这些属性的注释并保存文件。删除注释之后,文件的这个部分类似于清单 16。

清单 16. 启用 pureQuery 批处理所需的 hibernate.cfg.xml 中的必要属性
<property name="hibernate.jdbc.factory_class">
     com.ibm.compdq.hibernate3.PDQBatcherFactory</property> 
<event type="flush">
<listener class="com.ibm.pdq.hibernate3.listener.PDQFlushListener"/>
</event>

在异构批处理模式下运行应用程序

清单 17 显示了经过配置的 persistence.xml 文件,可在同时启用 pureQuery 静态 SQL 和异构批处理的情况下运行应用程序。它定义实体、数据库连接属性和其他必要的配置属性。

batch_size 属性控制 JDBC 批处理的大小。它还被 Integration Module 用来控制一个 pureQuery 批处理的大小。推荐的批处理大小介于 50 到 100 之间。批处理的大部分优势可在 1 到 25 的大小范围内看到。如果批量太大,您可能会收到一个 SQL 代码为 -805 的 SQL 异常。这意味着数据库服务器已用尽动态游标。

清单 17. Hibernate 样例应用程序的 persistence.xml
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">

<provider>com.ibm.pdq.hibernate3.PDQHibernatePersistence</provider>
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->

    <class>demo.CustomerInfo</class>     
    <class>demo.Customer</class> 
    <class>demo.District</class>
    <class>demo.Item</class>
    <class>demo.Order</class>
 		
<properties>
<property name="hibernate.connection.driver_class"
value="com.ibm.db2.jcc.DB2Driver"/>
					
<property name="hibernate.connection.url" 
value="jdbc:db2:demodb"/>
					
<property name="hibernate.connection.username" 
value="xx"/>
					
<property name="hibernate.connection.password" 
value="xx"/>  
        
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect"/>

<property name="hibernate.hbm2ddl.auto" 
value="update"/>

<property name="hibernate.jdbc.batch_size" 
value = "100"/>

<property name="hibernate.jdbc.factory_class" value = 
"com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory"/>

<property name="hibernate.ejb.event.flush" value = 
"com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener"/>

<property name="hibernate.connection.provider_class" value= 
"org.hibernate.connection.C3P0ConnectionProvider"/>

</properties>
</persistence-unit>

注意:如果您在使用 Informix Dynamic Server,那么就需要在 persistence.xml 中将 hibernate.dialect 设置为 InformixDialect,如下所示:
<property name = “hibernate.dialect” value = “org.hibernate.dialect.InformixDialect”/>

现在您可以通过执行 MainClient.java 运行样例应用程序。定制的 pureQuery 批处理程序确保执行异构批处理。

如果您在使用 hibernate.cfg.xml,可以执行使用 SessionFactory API 的 MainClientSessionFactory.java 类来运行样例应用程序。您还应当在应用程序路径中包含 c3p0.properties 文件,并指定 c3p0.maxStatementsPerConnection 属性。


比较样例应用程序运行时性能

本节描述在使用 pureQuery 异构处理模式运行样例应用程序时,如何确定其性能是否有所提升。

收集运行时间

在运行样例应用程序时,要确定 pureQuery 异构批处理是否提供运行时间效益,您需要分别在异构批处理模式和非异构批处理模式下运行应用程序。

获取运行时间的一个方法是使用 MainClient.javaMainClientSessionFactory.java 运行应用程序。该方法显示运行程序所需的总运行时间。

另一种方法是开启对批处理程序的跟踪。这可以让您真正看到 Integration Module 如何创建异构批处理,即向您展示批处理的起始时间、向批处理添加语句的时间,以及批处理结束的时间。样例应用程序包含一个名为 log4j.properties 的文件,您可以用它来开启对批处理程序的跟踪。批处理结束之后,当前目录中包含一个名为 demo.log 的文件,该文件包含的消息类似于清单 18。

清单 18. demo.log 中的跟踪消息
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - PureQuery batch started

Added to the batch: insert into District (d_city, d_name, d_next_o_id, 
   d_state, d_street_1, d_street_2, d_tax, d_ytd, d_zip, version, d_id) 
   values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: insert into Customer (city, fname, lname, state, 
  street, version, zipcode, c_balance, c_credit, c_credit_lim, c_data, 
  c_delivery_cnt, c_discount, c_payment_cnt, c_since, c_ytd_payment, 
  district_d_id, c_d_id, c_id) 
   values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: insert into Item (i_data, i_name, i_price, version, i_id) 
   values (?, ?, ?, ?, ?)

Added to the batch: insert into Order (district_d_id, itime, o_all_local, o_c_id, 
    o_carrier_id, o_entry_d, o_ol_cnt, version, o_d_id, o_id) 
      values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: update District set d_city=?, d_name=?, d_next_o_id=?, d_state=?, 
    d_street_1=?, d_street_2=?, d_tax=?, d_ytd=?, d_zip=?, version=? 
       where d_id=? and version=?

Added to the batch: update Customer set city=?, fname=?, lname=?, state=?, street=?, 
  version=?, zipcode=?,    c_balance=?, c_credit=?, c_credit_lim=?, c_data=?, 
   c_delivery_cnt=?, c_discount=?, c_payment_cnt=?, c_since=?, c_ytd_payment=?, 
    district_d_id=? where c_d_id=? and c_id=? and version=?

Added to the batch: update Item set i_data=?, i_name=?, i_price=?, version=? 
   where i_id=? and version=?

TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - About to execute the batch
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - Batch Executed.
  Executed batch size=7
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - Number of batches 
   executed in the session = 1

样例结果

本文作者将批处理大小设置为 100,在装有 DB2 的一台本地机和一台远程机上测试了样例应用程序。该测试在 DB2 for Linux, UNIX, and Windows 上产生了以下结果:

免责声明

本文档中包含的任何性能数据都是在各种受控实验室环境中测得的,仅作参考之用。用户不应在其自己的环境中将这些性能数字作为系统性能标准。在其他操作环境中获得的数据可能会有明显的不同。本文档的用户应当验证其特定环境的适用数据。

  • 当 DB2 和样例应用程序在一台本地机上运行时,根据每个事务的对象数,pureQuery 通过 JDBC 将运行时性能提升了超过 40%。如图 7 所示。每个对象创建有 7 个 SQL 语句(反过来,每个对象又创建有 7 个不同的实体对象)。
  • 当 DB2 在一台远程机上运行且样例应用程序在一台本地机上运行时,根据每个事务的对象数,运行时性能从 12% 提升到超过 50%。如图 8 所示。每个对象创建有 7 个 SQL 语句(反过来,每个对象又创建有 7 个不同的实体对象)。

在图 7 中,x 轴表示每个事务的对象数。y 轴表示事务所需时间,以毫秒为单位。注意,图表显示 JDBC 批处理比 pureQuery 需要更多运行时间。

图 7. 本地数据库服务器上的 JDBC 与 pureQuery
轴上的第一个点表示 4 个对象。JDBC 所用时间是 9.9,purequery 所用时间为 3.32。最后一个点表示的对象数是 84。jdbc 所用时间是 40.2 ms,而 purequery 所用时间是 26.1 ms

在图 8 中,x 轴表示每个事务的对象数。y 轴表示事务所需时间,以毫秒为单位。注意,图表显示 JDBC 批处理比 pureQuery 需要更多运行时间。还要注意,在本例中,随着每个事务的对象数的增多,pureQuery 与 JDBC 之间的 δ 运行时间增加。

图 8. 远程数据库服务器上的 JDBC 与 pureQuery
随着对象的增多,远程机上的时间节约越明显。对于 4 个对象,jdbc 所需时间是 9.7ms,而 purequery 所用时间是 8.6 ms。然而对于 84 个对象,jdbc 所用时间是 80.9ms,而 purequery 所用时间是 35.2 ms

联合使用静态 SQL 和异构批处理

静态 SQL 和异构批处理特性都是正交的。这意味着,一个 Hibernate 应用程序可以同时使用静态 SQL 和异构批处理,也可以独立使用每个特性。设置每个特性所需的步骤没有重叠。要设置静态 SQL,遵循 为 Hibernate 应用程序启用 pureQuery 静态 SQL 中列出的步骤。要设置异构批处理,遵循 为 Hibernate 应用程序启用 pureQuery 异构批处理 中列出的步骤。要同时设置两者,只需同时遵循这两个部分的步骤即可;次序无关紧要。


使用增量捕捉模式收集 Criteria 查询

如果您的 Hibernate 应用程序使用 Criteria 查询,那么可以使用增量捕捉模式获取 Criteria 查询的 SQL 语句,并将其转化为静态 SQL。为此,可以如清单 19 所示更改 pdq.properties。(HibernateGen.bat 的后续版本预期支持为 Criteria 查询生成 SQL 语句)。

清单 19. 用于增量步骤模式的 pdq.properties
pdq.captureMode=ON
pdq.executionMode=STATIC
pdq.pureQueryXml=test.pdqxml
pdq.OutputPureQueryXml=incremental_capture.pdqxml

在运行应用程序时,它创建一个名为 incremental_capture.pdqxml 的新文件,该文件包含由 HibernateGen 命令创建的 pdqxml 文件中没有的 SQL。您可以使用 pureQuery Merge 工具来合并两个文件。这样就有了一个统一的 pdqxml,包含同时来自两个文件的 SQLs。清单 20 显示如何运行 Merge 工具。

清单 20. 运行 pureQuery Merge 工具
> java com.ibm.pdq.tools.Merge

  -outputPureQueryXml test_Merged.pdqxml

  -baseFile test.pdqxml

  -inputPureQueryXml incremental_capture.pdqxml

有关 pureQuery Merge utility 的更多信息,参阅 参考资料 部分。

运行清单 20 中所示的 Merge 工具样例之后,就可随时绑定 test_Merged.pdqxml 文件。首先在 test_Merged.pdqxml 上运行 StaticBinder,如 清单 11 所示。然后如清单 21 所示更改 pdq.properties。

清单 21. 增量捕捉模式关闭之后执行静态 SQL 的 pdq.properties
pdq.captureMode=OFF
pdq.executionMode=STATIC
pdq.pureQueryXml=test_Merged.pdqxml

再次运行应用程序。现在来自 Criteria 查询的 SQL 也会静态执行。


结束语

本文是一个由两个部分组成的系列文章的第 1 部分。介绍了如何对 Hibernate 应用程序(Hibernate JPA 应用程序和 Hibernate 原生应用程序)使用面向 pureQuery 和 Hibernate 的 IBM Integration Module。简要概述了如何使用 pureQuery 客户端和非正式运行时性能度量。本系列文章的第 2 部分将专注于 iBATIS 应用程序。

在使用静态 SQL 时,面向 pureQuery 和 Hibernate 的 IBM Integration Module 能提供显著的 DB2 性能增益。当为适当的应用程序应用异构批处理时,它还提供显著的 DB2 运行时增益。这些性能改进对于 J2EE 和 J2SE 环境都适用。


致谢

作者希望感谢 Asim Singh 和 Ambrish Bhargava 审阅本文并给出不错的反馈。


下载

描述名字大小
本文的 Hibernate 样例应用程序DemoHibApp.zip27KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management, Open source, Java technology
ArticleID=591372
ArticleTitle=使用 pureQuery 加速 Hibernate 和 iBATIS 应用程序,第 1 部分: 使用面向 Hibernate 和 pureQuery 的 IBM Integration Module
publish-date=11242010